- initial import

This commit is contained in:
2018-06-05 11:05:37 +03:00
commit e1a4931375
4673 changed files with 1383093 additions and 0 deletions

View File

@@ -0,0 +1,175 @@
cmake_minimum_required(VERSION 2.6)
project(jrtplib)
set(VERSION 3.9.1)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
set (_DEFAULT_LIBRARY_INSTALL_DIR lib)
if (EXISTS "${CMAKE_INSTALL_PREFIX}/lib32/" AND CMAKE_SIZEOF_VOID_P EQUAL 4)
set (_DEFAULT_LIBRARY_INSTALL_DIR lib32)
elseif (EXISTS "${CMAKE_INSTALL_PREFIX}/lib64/" AND CMAKE_SIZEOF_VOID_P EQUAL 8)
set (_DEFAULT_LIBRARY_INSTALL_DIR lib64)
endif ()
set(LIBRARY_INSTALL_DIR "${_DEFAULT_LIBRARY_INSTALL_DIR}" CACHE PATH "Library installation directory")
if(NOT IS_ABSOLUTE "${LIBRARY_INSTALL_DIR}")
set(LIBRARY_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIBRARY_INSTALL_DIR}")
endif()
include(CheckCXXCompilerFlag)
include(CheckIncludeFile)
include(CheckIncludeFileCXX)
include(CheckCXXSourceCompiles)
include(TestBigEndian)
include(${PROJECT_SOURCE_DIR}/cmake/Macros.cmake)
find_package(JThread)
set(JRTPLIB_LINK_LIBS "")
set(JRTPLIB_INTERNAL_INCLUDES "")
set(JRTPLIB_EXTERNAL_INCLUDES "")
add_additional_stuff(JRTPLIB_EXTERNAL_INCLUDES JRTPLIB_LINK_LIBS)
jrtplib_support_option("Support SDES PRIV items" JRTPLIB_SUPPORT_SDESPRIV RTP_SUPPORT_SDESPRIV ON "// No support for SDES PRIV items")
jrtplib_support_option("Support the probation mechanism for a new source" JRTPLIB_SUPPORT_PROBATION RTP_SUPPORT_PROBATION ON "// Do not wait for a number of consecutive packets to validate source")
jrtplib_support_option("Support sending RTCP APP packets" JRTPLIB_SUPPORT_SENDAPP RTP_SUPPORT_SENDAPP ON "// No direct support for sending RTCP APP packets")
jrtplib_support_option("Support sending unknown RTCP packets" JRTPLIB_SUPPORT_RTCPUNKNOWN RTP_SUPPORT_RTCPUNKNOWN OFF "// No support for sending unknown RTCP packets")
jrtplib_support_option("Support memory management mechanism" JRTPLIB_SUPPORT_MEMORYMGMT RTP_SUPPORT_MEMORYMANAGEMENT ON "// No memory management support")
jrtplib_include_test(sys/filio.h RTP_HAVE_SYS_FILIO "// Don't have <sys/filio.h>")
jrtplib_include_test(sys/sockio.h RTP_HAVE_SYS_SOCKIO "// Don't have <sys/sockio.h>")
jrtplib_include_test(ifaddrs.h RTP_SUPPORT_IFADDRS "// No ifaddrs support")
if (JTHREAD_FOUND)
set(V "ON")
else (JTHREAD_FOUND)
set(V "OFF")
endif (JTHREAD_FOUND)
option(JTHREAD_ENABLED "Thread support" ${V})
if (JTHREAD_ENABLED)
set (RTP_SUPPORT_THREAD "#define RTP_SUPPORT_THREAD")
if (JTHREAD_FOUND)
save_paths(JRTPLIB_EXTERNAL_INCLUDES "${JTHREAD_INCLUDE_DIRS}")
save_paths(JRTPLIB_LINK_LIBS "${JTHREAD_LIBRARIES}")
endif(JTHREAD_FOUND)
else (JTHREAD_ENABLED)
set (RTP_SUPPORT_THREAD "// No support for JThread was enabled")
endif (JTHREAD_ENABLED)
if (CMAKE_CROSSCOMPILING)
option (JRTPLIB_USE_BIGENDIAN "Target platform is big endian" ON)
if (JRTPLIB_USE_BIGENDIAN)
set(RTP_ENDIAN "#define RTP_BIG_ENDIAN")
else (JRTPLIB_USE_BIGENDIAN)
set(RTP_ENDIAN "// Little endian system")
endif (JRTPLIB_USE_BIGENDIAN)
else (CMAKE_CROSSCOMPILING)
test_big_endian(JRTPLIB_BIGENDIAN)
if (JRTPLIB_BIGENDIAN)
set(RTP_ENDIAN "#define RTP_BIG_ENDIAN")
else (JRTPLIB_BIGENDIAN)
set(RTP_ENDIAN "// Little endian system")
endif (JRTPLIB_BIGENDIAN)
endif (CMAKE_CROSSCOMPILING)
jrtplib_test_feature(socklentest RTP_SOCKLENTYPE_UINT TRUE "// socklen_t is 'int'")
jrtplib_test_feature(ipv4mcasttest RTP_SUPPORT_IPV4MULTICAST FALSE "// No IPv4 multicasting support")
jrtplib_test_feature(salentest RTP_HAVE_SOCKADDR_LEN FALSE "// No sa_len member in struct sockaddr")
jrtplib_test_feature(getloginrtest RTP_SUPPORT_GETLOGINR FALSE "// Not using getlogin_r")
jrtplib_test_feature(ipv6test RTP_SUPPORT_IPV6 FALSE "// No IPv6 support")
jrtplib_test_feature(ipv6mcasttest RTP_SUPPORT_IPV6MULTICAST FALSE "// No IPv6 multicasting support")
check_cxx_source_compiles("#include <stdint.h>\n#include <sys/types.h>\nint main(void) { size_t a = 0 ; size_t b = a; uint32_t x = 0; uint32_t y = x; return 0; }" JRTPLIB_STDINT)
if (JRTPLIB_STDINT)
set(RTP_INTTYPE_HEADERS "#include <stdint.h>\n#include <sys/types.h>")
else (JRTPLIB_STDINT)
check_cxx_source_compiles("#include <inttypes.h>\n#include <sys/types.h>\nint main(void) { uint32_t x = 0; uint32_t y = x; return 0; }" JRTPLIB_INTTYPES)
if (JRTPLIB_INTTYPES)
set(RTP_INTTYPE_HEADERS "#include <inttypes.h>\n#include <sys/types.h>\n")
else (JRTPLIB_INTTYPES)
if (NOT UNIX AND WIN32)
set(RTP_INTTYPE_HEADERS "#include \"rtptypes_win.h\"")
else (NOT UNIX AND WIN32)
set(RTP_INTTYPE_HEADERS "#error Could not find header files that define types like 'uint32_t'. Please edit the file ${PROJECT_BINARY_DIR}/src/rtptypes_unix.h and make sure that the following types are defined: int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t")
message("\n\nError: Could not find header files that define types like 'uint32_t'.\nPlease edit the file ${PROJECT_BINARY_DIR}/src/rtptypes_unix.h\nand make sure that the following types are defined: \nint8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t\n\n")
endif (NOT UNIX AND WIN32)
endif (JRTPLIB_INTTYPES)
endif (JRTPLIB_STDINT)
if (NOT UNIX AND WIN32)
set(RTP_WINSOCK_HEADERS "#if defined(WIN32) || defined(_WIN32_WCE)\n #include <winsock2.h> \n #include <ws2tcpip.h>\n#ifndef _WIN32_WCE\n #include <sys/types.h>\n#endif // _WIN32_WCE\n#endif // WIN32 || _WIN32_WCE\n")
endif (NOT UNIX AND WIN32)
if (NOT UNIX)
set(JRTPLIB_COMPILE_STATIC ON CACHE BOOL "Flag indicating if a static library should be built, or a dynamic one")
list(APPEND JRTPLIB_LINK_LIBS "ws2_32")
endif (NOT UNIX)
if (UNIX OR JRTPLIB_COMPILE_STATIC)
set(JRTPLIB_IMPORT "")
set(JRTPLIB_EXPORT "")
else (UNIX OR JRTPLIB_COMPILE_STATIC)
set(JRTPLIB_IMPORT "__declspec(dllimport)")
set(JRTPLIB_EXPORT "__declspec(dllexport)")
endif (UNIX OR JRTPLIB_COMPILE_STATIC)
configure_file("${PROJECT_SOURCE_DIR}/src/rtptypes.h.in" "${PROJECT_BINARY_DIR}/src/rtptypes.h")
configure_file("${PROJECT_SOURCE_DIR}/src/rtpconfig.h.in" "${PROJECT_BINARY_DIR}/src/rtpconfig.h")
save_paths(JRTPLIB_INTERNAL_INCLUDES "${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/src")
add_subdirectory(src)
add_subdirectory(examples)
if (UNIX)
get_target_property(JRTPLIB_LOCAL_LIBRARY_NAME jrtplib-shared LOCATION)
get_filename_component(JRTPLIB_LIBNAME "${JRTPLIB_LOCAL_LIBRARY_NAME}" NAME)
set(JRTPLIB_LIBS "${LIBRARY_INSTALL_DIR}/${JRTPLIB_LIBNAME}")
else (UNIX)
if (JRTPLIB_COMPILE_STATIC)
get_target_property(JRTPLIB_LOCAL_LIBRARY_NAME jrtplib-static RELEASE_LOCATION)
get_filename_component(JRTPLIB_LIBNAME_RELEASE "${JRTPLIB_LOCAL_LIBRARY_NAME}" NAME_WE)
get_target_property(JRTPLIB_LOCAL_LIBRARY_NAME jrtplib-static DEBUG_LOCATION)
get_filename_component(JRTPLIB_LIBNAME_DEBUG "${JRTPLIB_LOCAL_LIBRARY_NAME}" NAME_WE)
else (JRTPLIB_COMPILE_STATIC)
get_target_property(JRTPLIB_LOCAL_LIBRARY_NAME jrtplib-shared RELEASE_LOCATION)
get_filename_component(JRTPLIB_LIBNAME_RELEASE "${JRTPLIB_LOCAL_LIBRARY_NAME}" NAME_WE)
get_target_property(JRTPLIB_LOCAL_LIBRARY_NAME jrtplib-shared DEBUG_LOCATION)
get_filename_component(JRTPLIB_LIBNAME_DEBUG "${JRTPLIB_LOCAL_LIBRARY_NAME}" NAME_WE)
endif (JRTPLIB_COMPILE_STATIC)
set(JRTPLIB_LIBS optimized "${LIBRARY_INSTALL_DIR}/${JRTPLIB_LIBNAME_RELEASE}.lib"
debug "${LIBRARY_INSTALL_DIR}/${JRTPLIB_LIBNAME_DEBUG}.lib")
endif (UNIX)
set(JRTPLIB_INCDIRS ${JRTPLIB_EXTERNAL_INCLUDES} ${CMAKE_INSTALL_PREFIX}/include)
set(JRTPLIB_LIBS ${JRTPLIB_LIBS} ${JRTPLIB_LINK_LIBS})
remove_empty(JRTPLIB_INCDIRS)
list(REMOVE_DUPLICATES JRTPLIB_INCDIRS)
remove_empty(JRTPLIB_LIBS)
foreach(ARG ${JRTPLIB_LIBS})
set(JRTPLIB_LIBS_CMAKECONFIG "${JRTPLIB_LIBS_CMAKECONFIG} \"${ARG}\"")
endforeach()
foreach(ARG ${JRTPLIB_INCDIRS})
set(JRTPLIB_INCDIRS_CMAKECONFIG "${JRTPLIB_INCDIRS_CMAKECONFIG} \"${ARG}\"")
endforeach()
configure_file("${PROJECT_SOURCE_DIR}/cmake/JRTPLIBConfig.cmake.in" "${PROJECT_BINARY_DIR}/cmake/JRTPLIBConfig.cmake")
install(FILES "${PROJECT_BINARY_DIR}/cmake/JRTPLIBConfig.cmake" DESTINATION ${LIBRARY_INSTALL_DIR}/cmake/JRTPLIB)
if (UNIX)
foreach(ARG ${JRTPLIB_LIBS})
set(JRTPLIB_LIBS_PKGCONFIG "${JRTPLIB_LIBS_PKGCONFIG} ${ARG}")
endforeach()
foreach(ARG ${JRTPLIB_INCDIRS})
set(JRTPLIB_INCDIRS_PKGCONFIG "${JRTPLIB_INCDIRS_PKGCONFIG} -I${ARG}")
endforeach()
configure_file(${PROJECT_SOURCE_DIR}/pkgconfig/jrtplib.pc.in ${PROJECT_BINARY_DIR}/pkgconfig/jrtplib.pc)
install(FILES ${PROJECT_BINARY_DIR}/pkgconfig/jrtplib.pc DESTINATION ${LIBRARY_INSTALL_DIR}/pkgconfig)
endif (UNIX)

354
src/libs/jrtplib/ChangeLog Normal file
View File

@@ -0,0 +1,354 @@
November 8, 2011
JRTPLIB ChangeLog
-----------
3.9.1 (November 2011)
* Fixed a bug in the CMake configuration: was unable to handle
path names with spaces.
* Fixed bug in rtcpsdespacket.h: end namespace curly bracket
was in wrong place.
* In an MS-Windows environment you can now choose to build a
DLL instead of a static library.
3.9.0 (July 2011)
* Switched to CMake build system.
* Added the RTPByteAddress class, which can be used to describe
a host/port combination in a very general way.
* Added the RTPExternalTransmitter class which can be used if
one would like to use a transmission mechanism other than
the UDP based transmitters.
* Placed everything in namespace 'jrtplib'.
3.8.2 (February 2011)
* Fixed bug in RTPRandomRand48. The uint16_t version used a
& 0xff instead of & 0xffff. Thanks to Alexey Kumkov
(crazykum@ukr.net) for bringing this to my attention.
3.8.1 (October 2010)
* Initialization of the RTPRandomRandS class didn't work as
intended, causing the fall-back class RTPRandomRand48 always
being used on the Win32 platform.
3.8.0 (September 2010)
* Fixed bug in RTPSources implementation. An incorrect
'GotoNextElement' call was replaced by a 'GotoPreviousElement'
call.
* Added functionality to send unknown RTCP packets. Patch
was supplied by Tom Harper (d.thomas.harper@gmail.com)
* Fixed bug in INF_GetEstimatedTimestampUnit (possibility of
division by zero). Thanks to Gilson Yi (gilson.yi@gmail.com)
for bringing this to my attention.
* Added some code to allow a specific SSRC to be used.
* Fixed bug in jitter calculation code. Thanks to Uwe Andersen
(uandersen@mayah.com) for bringing this to my attention.
* Added OnPollThreadStart and OnPollThreadStop to RTPSession.
Thanks to Daniele Barzotti (daniele.barzotti@eurocomtel.com)
for suggesting this.
* Added method to RTPSessionParams to force a specific CNAME.
Thanks to Lars Rohwedder (L.Rohwedder@mocotec.de) for the
suggestion.
* Removed old RTPRandom code and made RTPRandom an abstract
interface. Added a /dev/urandom implementation, a rand_s
implementation and a rand48 implementation. By default,
/dev/urandom and rand_s are tried, and rand48 is used as a
fall-back mechanism.
3.7.1 (May 2007)
* Fixed bug in the CurrentTime implementation (Win32/WinCE version).
Thanks to Dani Baeyens (dani@warp.es) and Eric Johnson
(EJohnson@pelco.com) for helping me solve this problem.
3.7.0 (January 2007)
* Send and receive socket buffer sizes can now be set in the
transmission parameters. Thanks to Dmitry Shandyba
(Dmitry.Shandyba@materialise.kiev.ua) for suggesting this.
* Changed a 'htons' call to a 'ntohs' call in ShouldAcceptData
in both the IPv4 and IPv6 transmitters.
* Fixed bug in RTPIPv6Destination. Thanks to Yi-Huan Chan
(yhchan@csie.nctu.edu.tw) and Franco Sinhori
(francosinhori@gmail.com) for bringing this to my attention.
3.6.0 (June 2006)
* Added a constructor to the RTCPCompoundPacket class to be able
to parse a compound packet out of a byte array (and not only
out of an RTPRawPacket instance).
* Added a method to RTPSession to send RTCP APP packets. Thanks
to Herman Bastiaens (herman.bastiaens@student.uhasselt.be)
for supplying the patch.
* Fixed Win32 rand_s bug. Thanks to Jeremy Noring
(jnoring@wilife.com) for supplying the patch.
* Removed the GetNumRTPPacketsSent and GetNumRTCPPacketsSent
functions in the transmitter. The counts were only used to
check if packets had been sent. Now, a flag in RTPSession is
used for this purpose.
* Added memory management support.
* Added a member function to RTPSession which allows passing an
RTPTransmitter instance.
* The instances in the destination lists now store struct
sockaddr variables. This makes sending data to each destination
more efficient.
3.5.2 (March 2006)
* Fixed bug in the random number functions which are used with
MS Visual Studio 2005. Thanks to Jun Ohasi (jun@jnb.odn.ne.jp)
for bringing the incorrect use of rand_s to my attention.
* Changed types like u_int32_t to types like uint32_t in the
documentation.
3.5.1 (March 2006)
* Fixed bug in RTCP scheduler. Due to -= operation on an RTPTime
instance, an incredibly large scheduling interval could be
calculated.
3.5.0 (March 2006)
* Now, the define RTP_SNPRINTF is used instead of snprintf,
_snprintf or _snprintf_s.
* In the RTPSources member function MultipleTimeouts, I neglected
to call the OnRemoveSource virtual function. Thanks to Adam Love
(alove@exceptionalinnovation.com) for bringing this to my attention.
* Added a OnSendRTCPCompoundPacket member function to the RTPSession
class. Useful for inspecting outgoing data.
* Modified the templates somewhat. Should cause less compiler problems
this way. Thanks tot Chris Hamilton (chamilton@cs.dal.ca) for
providing this solution.
* On Win32, if possible the functions rand_s and srand_s are now used.
3.4.0 (January 2006)
* Changed u_int32_t like types to uint32_t like types. Thanks to
Panagiotis Issaris (takis.issaris@uhasselt.be) for informing me
that these are C99 compliant.
* Changed sprintf functions to safer snprintf functions. Thanks to
Panagiotis Issaris (takis.issaris@uhasselt.be) for pointing this
out.
* Fixed bug in RTPSources (counters were not reset when the source
table was cleared). Thanks to Justin Matthews (jmatthewsr@yahoo.com)
for pointing this out.
* Fixed bug in RTPHashTable and RTPKeyHashTable. Thanks to
Tom Pijsel (tom.pijsel@twelvecubes.com) for bringing this to my
attention.
* Fixed bug in example3.cpp
3.3.0 (October 2005)
* Now it is possible to use a user-defined transmission component.
* Added GStreamer transmission component written by Philippe Khalaf
(burger@speedy.org).
3.2.1 (September 2005)
* The library wouldn't compile when probation support was disabled.
Thanks to Herman Bastiaens (herman.bastiaens@student.luc.ac.be) for
bringing this to my attention.
* When parsed from an RTPRawPacket, the receive time is also stored
in the RTPPacket instance.
3.2.0 (September 2005)
* Modified the routine in the RTPSession class which creates the
CNAME. Aparently on some systems, the 'getlogin' call returns
null. As an alternative, the library uses getenv("LOGNAME").
Thanks to Mark Schiffmann (schima@neumann-elektronik.com) for
mentioning this to me.
* Added a OnBYEPacket method to the RTPSession class. Thanks to
Sigrid Thijs (sthijs@androme.be) for suggesting this.
* When probation support is enabled, a probation type can be selected
when the session is created. Supported types are "No probation",
"Use probation, but store packets" and "Use probation and discard
packets received in probation mode". Thanks to Chris Flerackers
(cflerackers@androme.be) for suggesting this feature.
* Added a parameter to WaitForIncomingData which indicates if
data is available when the function returns. Based on a suggestion
by Uwe Andersen (uandersen@mayah.com).
* Now using getifaddrs (if possible) to obtain our own IP addresses
(both in IPv4 version and IPv6 version).
* IPv6 code in Win32 version now works, but Visual Studio 2005 beta
has to be used. Thanks to Yi-Huan Chan (yhchan@csie.nctu.edu.tw)
for contributing some code.
* Added Win32 code for GetLocalIPList_Interfaces (both IPv4 and IPv6).
Thanks to Ivan Makushkin (camry@pisem.net) for pointing out how
this could be done.
* Added an option to use a SR packet when sending a BYE message.
Previously, a RR packet was always used, even if a session is
actually an active sender of data. Thanks to Uwe Andersen
(uandersen@mayah.com) for bringing this to my attention.
* Fixed bug in CNAME creation.
* Added WinCE support. Thanks to Maarten Daniels
(maarten.daniels@uhasselt.be) for supplying patches.
* Changed the CurrentTime implementation for the MS-Windows version.
Thanks to Maarten Daniels (maarten.daniels@uhasselt.be) and Chris
Flerackers (cflerackers@androme.be).
3.1.0 (October 2004)
* Added a callback OnPollThreadStep which is called at the end of
each loop of the poll thread
* Added the examples subdirectory to the package
* Fixed bug in rtpudpv4transmitter.cpp and rtpudpv6transmitter.cpp
which caused an infinite loop in LeaveAllMulticastGroups. Thanks
to Stijn Agten (stijn.agten@luc.ac.be) for pointing this out.
* Added a function GetTransmissionInfo to the RTPTransmitter class
(and subclasses). The function will return some additional
information about the transmitter, like local IP addresses and
socket descriptors.
3.0.2 (September 2004)
* Bugfix in rtpinternalsourcedata.cpp. The bug caused a crash when
duplicate packets were received. Thanks to Dominique Prunier
(dominique.prunier@micromedia-int.com) for informing me about
this.
3.0.1 (September 2004)
* Bugfix in rtpudpv4transmitter.cpp and rtpudpv6transmitter.cpp in
method SetReceiveMode
* Removed unused 'acceptownpackets' variable from
rtpudpv4transmitter.cpp and rtpudpv6transmitter.cpp
* Added a 'Dump' function (for debugging) in RTPUDPv4Transmitter
and RTPUDPv6Transmitter
* Now using JThread 1.1.0
3.0.0 (August 2004)
* Complete rewrite of the library to provide better extensibility
and compliance with RFC 3550
* Changes from the 2.x series:
- The 2.x series was created with the idea that the user
would only need to use the RTPSession class which meant
that the other classes were not very useful by themselves.
This version on the other hand, aims to provide many
useful components to aid the user in building RTP capable
applications.
- In this version, the code which is specific for the
underlying protocol by which RTP packets are transported,
is bundled in a class which inherits its interface from a
class called RTPTransmitter. This makes it easy for
different underlying protocols to be supported. Currently
there is support for UDP over IPv4 and UDP over IPv6.
2.9 (July 2004)
* Fixed bug in rtpsrclist.cpp. Thanks to Lukasz Bobowiec
(bobowiec@icslab.agh.edu.pl)
* Added function in RTPSourceData which returns the IP address
* Changed the random routines. Thanks to Jaap Keuter
(jaap.keuter@xs4all.nl)
* Made the shared library link against libstdc++ if possible.
Thanks to Anatoly Yakovenko (aeyakovenko@yahoo.com) for the
suggestion.
2.8 (January 2004)
* Added code to avoid a crash when receiving a malformed packet
* Fixed a memory leak (forgot to free memory when a malformed
packet was discarded)
* Changed debug routines for memory tracking
2.7b (November 2003)
* Only added --enable-fpic and --enable-fPIC to the configure script
2.7 (December 2002)
* Fixed important bug in rtpsources.cpp. This bug could cause
source information to get lost and could create a memory leak.
* Improved support for AIX in multicasting code (uses _AIX define).
Thanks to Klaus Matuschek (klaus.matuschek@infonova.com)
* Fixed possible buffer overrun in rtpcontributingsources.cpp
2.6 (January 2002)
* This release only contains some minor changes
* An 'install' target was added to the Makefile
* Some newlines were added add the end of certain files to avoid
compiler warnings
* Improved the jitter calculations somewhat
2.5 (December 2000)
* Added the possibility for the user to receive the raw RTCP packets.
* Fixed a bug in RTPContributingSources::CreateLocalCNAME(). In this
routine, the wrong length was passed to 'gethostname'. Thanks to
Sergey V.Shpital (sergey@page.net.ru) for bringing this to my
attention.
* Added a routine to set the Type of Service (ToS) field of the
outgoing packets (both RTP and RTCP). Thank to Philippe Cardon
(philippe.cardon@bt.com) for writing this code.
* Fixed a bug in the 'packets lost' calculation. Thank to Domingo
Cuevas Jr. (dcj@onebox.com) for helping me find this bug.
* Fixed a bug in the sequence number and jitter calculation: when
packets were received out of order, the sequence numbers and
jitter got messed up. Many thanks to Mohammad Tawsheeq Russool
(m.russool@eim.surrey.ac.uk) for helping me track down these
bugs.
* Added the possibility to set the timestamp unit for a particular
source. Previously, it was assumed that their timestamp unit
was the same as that of the local session.
2.4 (July 2000)
* Fixed a bug which caused all CSRS's except one to be incorrect.
* Added RTP header extension support (for both sending and receiving).
* Added some things (which should have been there already) to
RTPPacket.
* Adjusted the way in which the login name is retrieved on unix-like
systems. First I used a call to 'getlogin', but apparently this
function messes with timers through the use of 'alarm' calls (at
least on Linux). Now, I use a combination of 'geteuid' and
'getpwuid' to obtain the necessary information. This does not
have that problem and is a lot cleaner since it doesn't depend
on login info (utmp) like 'getlogin'. Thanks to Roberto Jung Drebes
(drebes@inf.ufrgs.br) for pointing out the timer-problem.
* Made a LaTeX version of the manual and tutorial. Looks a lot nicer.
* Made it possible for the user to specify the local IP address
instead of letting the library figure it out itself.
* Fixed a bug which caused the 'fraction lost' in a RR packet to be
zero all the time. Thanks to Domingo Cuevas Jr. (dcj@onebox.com) for
pointing this out.
* Rewrote the RTCP packet sending routines. Now, they are much cleaner
and much more understandable :)
* Added better support for RTCP 'APP' packets. You can now both send
and receive APP packets.
2.3 (April 2000)
* The routine which creates and sends RTCP packets is now a bit faster.
* Added a sample that demonstrates the round-trip time function.
* Added functions to RTPSourceData: now the time when the last RR or
SR report was received can be retrieved. Also, the round trip time
can be retrieved: this is calculated as suggested in RFC 1889.
* Fixed a bug: the LSR value was not calculated correctly, now it is
(or should be ;-) )
* Instead of specifying defines on the command line, they are now
defined in a config file. The unix version of this file is created
by the configure script.
* Added a member to RTPPacket which I had forgotten (the payload type,
which is obviously important :-) ).
* The library should now be able to work on a VxWorks platform. Thanks
to Dave Osborne (dosborne@argoneng.com) for his help.
* Added a tutorial and a small example application.
* Added some debugging routines (RTPDebug class) to check for memory
leaks. It turned out that there weren't any, so I'm pretty pleased ;)
* I've added a 'configure' script to make compilation a bit easier
across different platforms. Thanks to Qi Han (qh1c4@mizzou.edu) for
helping me to improve the support for the Solaris platform. Also
many thanks to Dario Maggiorini (dario@netdev.usr.dsi.unimi.it) for
helping me test the script on several platforms.
* Added multicasting support.
* A bug in rtpsourcedata.cpp was pointed out and fixed by Ramon Clout
(ramonc@win.tue.nl). Many thanks for this, Ramon.
2.2 (February 2000)
* Extra support for Sun and HP. Thanks to Henry Lau (hlau@nuera.com)
and Justin Matthews (jmatthews@nuera.com) for this information.
* The 'Poll' routine in rtpconnection.cpp has been altered. Now, the
routine should work even if there's that ioctl bug (previously, this
bug was only taken into consideration on a Windows platform).
Thanks to Justin Matthews (jmatthews@nuera.com) for his bugreport.
* Added some routines to RTPSession to get the local IP address and the
port number of the sending socket.
* 'install' rule added to the makefile.
* Added the define 'RTP_SOCKLENTYPE_UINT'. See README.TXT for more
information about this.
2.1 (December 1999)
* First release of jrtplib.
* Added member functions of RTPSession to retrieve the used sockets.
* Made the destination list faster by using a hash table.
2.0 (August 1999)
* First decent implementation of RTP. Entirely rewritten since 1.0.
1.0 (August 1999)
* First implementation of RTP. There were a lot of things that weren't
quite right and the organisation of the classes was quite nasty.
However, I learned a lot about RTP making this version, and so it
allowed me to make a good start on version 2.0.

1688
src/libs/jrtplib/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

View File

@@ -0,0 +1,22 @@
========================================================================
STATIC LIBRARY : jrtplib Project Overview
========================================================================
AppWizard has created this jrtplib library project for you.
No source files were created as part of your project.
jrtplib.vcproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////

0
src/libs/jrtplib/TODO Normal file
View File

View File

@@ -0,0 +1,37 @@
find_package(JThread QUIET NO_MODULE)
if (NOT JTHREAD_FOUND) # Config file could not be found
find_path(JTHREAD_INCLUDE_DIR jthread/jthread.h)
set(JTHREAD_INCLUDE_DIRS ${JTHREAD_INCLUDE_DIR})
if (UNIX)
find_library(JTHREAD_LIBRARY jthread)
if (JTHREAD_LIBRARY)
set(JTHREAD_LIBRARIES ${JTHREAD_LIBRARY})
find_library(JTHREAD_PTHREAD_LIB pthread)
if (JTHREAD_PTHREAD_LIB)
set(JTHREAD_LIBRARIES ${JTHREAD_LIBRARY} ${JTHREAD_PTHREAD_LIB})
endif(JTHREAD_PTHREAD_LIB)
endif (JTHREAD_LIBRARY)
else (UNIX)
find_library(JTHREAD_LIB_RELEASE jthread)
find_library(JTHREAD_LIB_DEBUG jthread_d)
if (JTHREAD_LIB_RELEASE OR JTHREAD_LIB_DEBUG)
set(JTHREAD_LIBRARIES "")
if (JTHREAD_LIB_RELEASE)
set(JTHREAD_LIBRARIES ${JTHREAD_LIBRARIES} optimized ${JTHREAD_LIB_RELEASE})
endif (JTHREAD_LIB_RELEASE)
if (JTHREAD_LIB_DEBUG)
set(JTHREAD_LIBRARIES ${JTHREAD_LIBRARIES} debug ${JTHREAD_LIB_DEBUG})
endif (JTHREAD_LIB_DEBUG)
endif (JTHREAD_LIB_RELEASE OR JTHREAD_LIB_DEBUG)
endif(UNIX)
endif (NOT JTHREAD_FOUND)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(JThread DEFAULT_MSG JTHREAD_INCLUDE_DIRS JTHREAD_LIBRARIES)

View File

@@ -0,0 +1,7 @@
set(JRTPLIB_FOUND 1)
set(JRTPLIB_INCLUDE_DIRS ${JRTPLIB_INCDIRS_CMAKECONFIG})
set(JRTPLIB_LIBRARIES ${JRTPLIB_LIBS_CMAKECONFIG})

View File

@@ -0,0 +1,104 @@
macro(jrtplib_support_option DESCRIPTION OPTIONNAME DEFINENAME DEFAULTVALUE EMPTYVALUE)
option(${OPTIONNAME} ${DESCRIPTION} ${DEFAULTVALUE})
if (${OPTIONNAME})
set(${DEFINENAME} "#define ${DEFINENAME}")
else (${OPTIONNAME})
set(${DEFINENAME} "${EMPTYVALUE}")
endif (${OPTIONNAME})
endmacro(jrtplib_support_option)
macro(jrtplib_include_test INCFILE DEFINENAME EMPTYVALUE)
check_include_file_cxx(${INCFILE} jrtplib_include_test_${DEFINENAME})
if (jrtplib_include_test_${DEFINENAME})
set(${DEFINENAME} "#define ${DEFINENAME}")
else (jrtplib_include_test_${DEFINENAME})
set(${DEFINENAME} "${EMPTYVALUE}")
endif (jrtplib_include_test_${DEFINENAME})
endmacro(jrtplib_include_test)
macro (jrtplib_test_feature FILENAME DEFINENAME INVERT EMPTYVALUE)
if (NOT DEFINED ${FILENAME}_RESULT)
try_compile(${FILENAME}_RESULT "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/tools/${FILENAME}.cpp"
OUTPUT_VARIABLE OUTVAR)
message(STATUS "Compiling ${FILENAME}.cpp")
set(BLA ${INVERT})
if (NOT BLA)
if (${FILENAME}_RESULT)
set(${DEFINENAME} "#define ${DEFINENAME}" CACHE INTERNAL "setting ${DEFINENAME} in rtpconfig.h")
message(STATUS "Compiling ${FILENAME}.cpp worked - setting ${DEFINENAME} in rtpconfig.h")
else (${FILENAME}_RESULT)
set(${DEFINENAME} "${EMPTYVALUE}" CACHE INTERNAL "")
message(STATUS "Compiling ${FILENAME}.cpp failed - no action necessary")
endif (${FILENAME}_RESULT)
else (NOT BLA)
if (NOT ${FILENAME}_RESULT)
set(${DEFINENAME} "#define ${DEFINENAME}" CACHE INTERNAL "setting ${DEFINENAME} in rtpconfig.h")
message(STATUS "Compiling ${FILENAME}.cpp failed - setting ${DEFINENAME} in rtpconfig.h")
else (NOT ${FILENAME}_RESULT)
set(${DEFINENAME} "${EMPTYVALUE}" CACHE INTERNAL "")
message(STATUS "Compiling ${FILENAME}.cpp worked - no action necessary")
endif (NOT ${FILENAME}_RESULT)
endif (NOT BLA)
endif (NOT DEFINED ${FILENAME}_RESULT)
endmacro (jrtplib_test_feature)
macro(save_paths VARNAME)
set (BLA "${ARGN}")
foreach(i IN LISTS BLA)
set (BLA2 "${i}")
if (BLA2)
list(APPEND ${VARNAME} "${i}")
endif (BLA2)
endforeach(i)
list(LENGTH ${VARNAME} BLA)
if (BLA GREATER 0)
list(REMOVE_DUPLICATES ${VARNAME})
endif (BLA GREATER 0)
endmacro(save_paths)
macro(remove_empty VARNAME)
set (remove_empty_NEWLIST "")
foreach(i IN LISTS ${VARNAME})
set (BLA2 "${i}")
if (BLA2)
list(APPEND remove_empty_NEWLIST "${i}")
endif (BLA2)
endforeach(i)
set(${VARNAME} "${remove_empty_NEWLIST}")
endmacro(remove_empty)
macro(apply_include_paths VARNAME)
set (BLA "${VARNAME}")
foreach(i IN LISTS BLA)
set (BLA2 "${i}")
if (BLA2)
include_directories("${i}")
endif (BLA2)
endforeach(i)
endmacro(apply_include_paths)
macro(add_additional_stuff INCVAR LIBVAR)
set(ADDITIONAL_INCLUDE_DIRS "" CACHE STRING "Additional include directories")
if (UNIX AND NOT WIN32)
set(ADDITIONAL_LIBRARIES "" CACHE STRING "Additional libraries to link against")
else (UNIX AND NOT WIN32)
set(ADDITIONAL_GENERAL_LIBRARIES "" CACHE STRING "Additional libraries to link against in both debug and release modes")
set(ADDITIONAL_RELEASE_LIBRARIES "" CACHE STRING "Additional libraries to link against in release mode")
set(ADDITIONAL_DEBUG_LIBRARIES "" CACHE STRING "Additional libraries to link against in debug mode")
set(ADDITIONAL_LIBRARIES "${ADDITIONAL_GENERAL_LIBRARIES}")
foreach(l IN LISTS ADDITIONAL_RELEASE_LIBRARIES)
list(APPEND ADDITIONAL_LIBRARIES optimized)
list(APPEND ADDITIONAL_LIBRARIES "${l}")
endforeach(l)
foreach(l IN LISTS ADDITIONAL_DEBUG_LIBRARIES)
list(APPEND ADDITIONAL_LIBRARIES debug)
list(APPEND ADDITIONAL_LIBRARIES "${l}")
endforeach(l)
endif (UNIX AND NOT WIN32)
save_paths(${INCVAR} "${ADDITIONAL_INCLUDE_DIRS}")
save_paths(${LIBVAR} "${ADDITIONAL_LIBRARIES}")
endmacro(add_additional_stuff)

View File

@@ -0,0 +1,351 @@
/**\mainpage JRTPLIB
*
* \author Jori Liesenborgs
* \author Developed at the The Expertise Centre for Digital Media (EDM), a research
* institute of the Hasselt University
*
* \section ack Acknowledgment
*
* I would like thank the people at the Expertise Centre for Digital Media
* for giving me the opportunity to create this rewrite of the library.
*
* \section intro Introduction
*
* This document describes JRTPLIB, an object-oriented
* library written in C++ which aims to help developers in using the
* Real-time Transport Protocol (RTP) as described in RFC 3550.
*
* The library makes it possible for the user to send and receive data
* using RTP, without worrying about SSRC collisions, scheduling and
* transmitting RTCP data etc. The user only needs to provide the library
* with the payload data to be sent and the library gives the user access
* to incoming RTP and RTCP data.
*
* \subsection idea Design idea
*
* The library provides several classes which can be helpful in
* creating RTP applications. Most users will probably only need the
* RTPSession class for building an application. This class
* provides the necessary functions for sending RTP data and handles
* the RTCP part internally.
*
* \subsection changes Changes from version 2.x
*
* One of the most important changes is probably the fact that this
* version is based on RFC 3550 and the 2.x versions were based upon
* RFC 1889 which is now obsolete.
*
* Also, the 2.x series was created with the idea that the user would
* only need to use the RTPSession class which meant that the
* other classes were not very useful by themselves. This version on
* the other hand, aims to provide many useful components to aid the
* user in building RTP capable applications.
*
* In this version, the code which is specific for the underlying
* protocol by which RTP packets are transported, is bundled in
* a class which inherits its interface from a class called
* RTPTransmitter. This makes it easy for different underlying
* protocols to be supported. Currently there is support for UDP over
* IPv4 and UDP over IPv6.
*
* For applications such as a mixer or translator using the
* RTPSession class will not be a good solution. Other components can
* be used for this purpose: a transmission component, an SSRC table,
* an RTCP scheduler etc. Using these, it should be much easier to
* build all kinds of applications.
* \section copyright Copyright license
*
* The library code uses the following copyright license:
*
* \code
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
* KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* \endcode
*
* There are two reasons for using this license. First, since this is the
* license of the 2.x series, it only seemed natural that this rewrite
* would contain the same license. Second, since the RTP protocol is
* deliberately incomplete RTP profiles can, for example, define additional
* header fields. The best way to deal with this is to adapt the library
* code itself and that's why I like to keep the license as free as
* possible.
*
* \section starting Getting started with the RTPSession class
*
* All classes and functions are part of the \c jrtplib namespace, so to
* simplify the code a bit, we'll declare that we're using this namespace:
* \code
* using namespace jrtplib;
* \endcode
* To use RTP, you'll have to create an RTPSession object. The constructor
* accepts two parameter, an instance of an RTPRandom object, and an instance
* of an RTPMemoryManager object. For now, we'll keep it simple and use the
* default settings, so this is our code so far:
*
* \code
* RTPSession session;
* \endcode
*
* To actually create the session, you'll have to call the Create member
* function which takes three arguments: the first one is of type RTPSessionParams
* and specifies the general options for the session. One parameter of this class
* must be set explicitly, otherwise the session will not be created successfully.
* This parameter is the timestamp unit of the data you intend to send and
* can be calculated by dividing a certain time interval (in seconds) by the
* number of samples in that interval. So, assuming that we'll send 8000 Hz
* voice data, we can use this code:
*
* \code
* RTPSessionParams sessionparams;
*
* sessionparams.SetOwnTimestampUnit(1.0/8000.0);
* \endcode
*
* The other session parameters will probably depend on the actual RTP profile
* you intend to work with.
*
* The second argument of the Create function is a pointer to an RTPTransmissionParams
* instance and describes the parameters for the transmission component. The third
* parameter selects the type of transmission component which will be used. By default,
* an UDP over IPv4 transmitter is used, and for this particular transmitter, the
* transmission parameters should be of type RTPUDPv4TransmissionParams. Assuming
* that we want our RTP portbase to be 8000, we can do the following:
*
* \code
* RTPUDPv4TransmissionParams transparams;
*
* transparams.SetPortbase(8000);
* \endcode
*
* Now, we're ready to call the Create member function of RTPSession. The return
* value is stored in the integer \c status so we can check if something went
* wrong. If this value is negative, it indicates that some error occurred.
* A description of what this error code means can be retrieved by calling
* RTPGetErrorString:
*
* \code
* int status = session.Create(sessionparams,&transparams);
* if (status < 0)
* {
* std::cerr << RTPGetErrorString(status) << std::endl;
* exit(-1);
* }
* \endcode
*
* If the session was created with success, this is probably a good point
* to specify to which destinations RTP and RTCP data should be sent. This is
* done by a call to the RTPSession member function AddDestination. This
* function takes an argument of type RTPAddress. This is an abstract
* class and for the UDP over IPv4 transmitter the actual class to be
* used is RTPIPv4Address. Suppose that we want to send our data to a
* process running on the same host at port 9000, we can do the following:
*
* \code
* uint8_t localip[]={127,0,0,1};
* RTPIPv4Address addr(localip,9000);
*
* status = session.AddDestination(addr);
* if (status < 0)
* {
* std::cerr << RTPGetErrorString(status) << std::endl;
* exit(-1);
* }
* \endcode
*
* If the library was compiled with JThread support, incoming data is
* processed in the background. If JThread support was not enabled at
* compile time or if you specified in the session parameters that no
* poll thread should be used, you'll have to call the RTPSession
* member function Poll regularly to process incoming data and to send
* RTCP data when necessary. For now, let's assume that we're working
* with the poll thread enabled.
*
* Lets suppose that for a duration of one minute, we want to send
* packets containing 20 ms (or 160 samples) of silence and we want
* to indicate when a packet from someone else has been received. Also
* suppose we have L8 data as defined in RFC 3551 and want to use
* payload type 96. First, we'll set some default values:
*
* \code
* session.SetDefaultPayloadType(96);
* session.SetDefaultMark(false);
* session.SetDefaultTimestampIncrement(160);
* \endcode
*
* Next, we'll create the buffer which contains 160 silence samples
* and create an RTPTime instance which indicates 20 ms or 0.020 seconds.
* We'll also store the current time so we'll know when one minute has
* passed.
*
* \code
* uint8_t silencebuffer[160];
*
* for (int i = 0 ; i < 160 ; i++)
* silencebuffer[i] = 128;
*
* RTPTime delay(0.020);
* RTPTime starttime = RTPTime::CurrentTime();
* \endcode
*
* Next, the main loop will be shown. In this loop, a packet containing
* 160 bytes of payload data will be sent. Then, data handling can
* take place but this part is described later in the text. Finally,
* we'll wait 20 ms and check if sixty seconds have passed:
*
* \code
* bool done = false;
* while (!done)
* {
* status = session.SendPacket(silencebuffer,160);
* if (status < 0)
* {
* std::cerr << RTPGetErrorString(status) << std::endl;
* exit(-1);
* }
*
* //
* // Inspect incoming data here
* //
*
* RTPTime::Wait(delay);
*
* RTPTime t = RTPTime::CurrentTime();
* t -= starttime;
* if (t > RTPTime(60.0))
* done = true;
* }
* \endcode
*
* Information about participants in the session, packet retrieval
* etc, has to be done between calls to the RTPSession member
* functions BeginDataAccess and EndDataAccess. This ensures that the
* background thread doesn't try to change the same data you're trying
* to access. We'll iterate over the participants using the
* GotoFirstSource and GotoNextSource member functions. Packets from
* the currently selected participant can be retrieved using the
* GetNextPacket member function which returns a pointer to an
* instance of the RTPPacket class. When you don't need the packet
* anymore, it has to be deleted. The processing of incoming data will
* then be as follows:
*
* \code
* session.BeginDataAccess();
* if (session.GotoFirstSource())
* {
* do
* {
* RTPPacket *packet;
* while ((packet = session.GetNextPacket()) != 0)
* {
* std::cout << "Got packet with extended sequence number "
* << packet->GetExtendedSequenceNumber()
* << " from SSRC " << packet->GetSSRC()
* << std::endl;
* session.DeletePacket(packet);
* }
* } while (session.GotoNextSource());
* }
* session.EndDataAccess();
* \endcode
*
* Information about the currently selected source can be obtained
* by using the GetCurrentSourceInfo member function of the RTPSession class.
* This function returns a pointer to an instance of RTPSourceData which
* contains all information about that source: sender reports from that
* source, receiver reports, SDES info etc.
*
* When the main loop is finished, we'll send a BYE packet to inform other
* participants of our departure and clean up the RTPSession class. Also,
* we want to wait at most 10 seconds for the BYE packet to be sent,
* otherwise we'll just leave the session without sending a BYE packet.
*
* \code
* delay = RTPTime(10.0);
* session.BYEDestroy(delay,"Time's up",9);
* \endcode
*
* The complete code of the program is given in \c example2.cpp.
*
* \section errors Error codes
*
* Unless specified otherwise, functions with a return type \c int
* will return a negative value when an error occurred and zero or a
* positive value upon success. A description of the error code can
* be obtained by using the RTPGetErrorString function, declared
* in rtperrors.h
*
* \section memory Memory management
*
* You can write you own memory manager by deriving a class from RTPMemoryManager.
* The following example shows a very basic implementation.
*
* \code
* class MyMemoryManager : public RTPMemoryManager
* {
* public:
* MyMemoryManager() { }
* ~MyMemoryManager() { }
*
* void *AllocateBuffer(size_t numbytes, int memtype)
* {
* return malloc(numbytes);
* }
*
* void FreeBuffer(void *p)
* {
* free(p);
* }
* };
* \endcode
*
* In the constructor of RTPSession, you can specify that you would like to use
* this memory manager:
*
* \code
* MyMemoryManager mgr;
* RTPSession session(0, &mgr);
* \endcode
*
* Now, all memory allocation and deallocation will be done using the AllocateBuffer
* and FreeBuffer implementations of \c mgr.
*
* The second parameter of the RTPMemoryManager::AllocateBuffer member function
* indicates what the purpose is of this memory block. This allows you to handle
* different kinds of data in different ways.
*
* With the introduction of the memory management system, the RTPSession class was
* extended with member function RTPSession::DeletePacket and RTPSession::DeleteTransmissionInfo.
* These functions should be used to deallocate RTPPacket instances and RTPTransmissionInfo
* instances respectively.
*
* \section contact Contact
*
* If you have any questions, remarks or requests about the library or
* if you think you've discovered a bug, you can contact me at
* \c jori(\c dot)\c liesenborgs(\c at)\c gmail(\c dot)\c com
*
* The home page of the library is
* http://research.edm.uhasselt.be/jori/jrtplib/jrtplib.html
*
* There is also a mailing list for the library. To subscribe to the list,
* send an e-mail to \c jrtplib-subscribe(\c at)\c edm(\c dot)\c uhasselt(\c dot)\c be
* and you'll receive further instructions.
*/

View File

View File

@@ -0,0 +1,12 @@
apply_include_paths("${JRTPLIB_INTERNAL_INCLUDES}")
apply_include_paths("${JRTPLIB_EXTERNAL_INCLUDES}")
foreach(IDX 1 2 3 4 5)
add_executable(example${IDX} example${IDX}.cpp)
if (UNIX OR JRTPLIB_COMPILE_STATIC)
target_link_libraries(example${IDX} jrtplib-static)
else ()
target_link_libraries(example${IDX} jrtplib-shared)
endif ()
endforeach(IDX)

View File

@@ -0,0 +1,150 @@
/*
Here's a small IPv4 example: it asks for a portbase and a destination and
starts sending packets to that destination.
*/
#include "rtpsession.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#ifndef WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif // WIN32
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace jrtplib;
//
// This function checks if there was a RTP error. If so, it displays an error
// message and exists.
//
void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}
//
// The main routine
//
int main(void)
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
RTPSession sess;
uint16_t portbase,destport;
uint32_t destip;
std::string ipstr;
int status,i,num;
// First, we'll ask for the necessary information
std::cout << "Enter local portbase:" << std::endl;
std::cin >> portbase;
std::cout << std::endl;
std::cout << "Enter the destination IP address" << std::endl;
std::cin >> ipstr;
destip = inet_addr(ipstr.c_str());
if (destip == INADDR_NONE)
{
std::cerr << "Bad IP address specified" << std::endl;
return -1;
}
// The inet_addr function returns a value in network byte order, but
// we need the IP address in host byte order, so we use a call to
// ntohl
destip = ntohl(destip);
std::cout << "Enter the destination port" << std::endl;
std::cin >> destport;
std::cout << std::endl;
std::cout << "Number of packets you wish to be sent:" << std::endl;
std::cin >> num;
// Now, we'll create a RTP session, set the destination, send some
// packets and poll for incoming data.
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
// IMPORTANT: The local timestamp unit MUST be set, otherwise
// RTCP Sender Report info will be calculated wrong
// In this case, we'll be sending 10 samples each second, so we'll
// put the timestamp unit to (1.0/10.0)
sessparams.SetOwnTimestampUnit(1.0/10.0);
sessparams.SetAcceptOwnPackets(true);
transparams.SetPortbase(portbase);
status = sess.Create(sessparams,&transparams);
checkerror(status);
RTPIPv4Address addr(destip,destport);
status = sess.AddDestination(addr);
checkerror(status);
for (i = 1 ; i <= num ; i++)
{
printf("\nSending packet %d/%d\n",i,num);
// send the packet
status = sess.SendPacket((void *)"1234567890",10,0,false,10);
checkerror(status);
sess.BeginDataAccess();
// check incoming packets
if (sess.GotoFirstSourceWithData())
{
do
{
RTPPacket *pack;
while ((pack = sess.GetNextPacket()) != NULL)
{
// You can examine the data here
printf("Got packet !\n");
// we don't longer need the packet, so
// we'll delete it
sess.DeletePacket(pack);
}
} while (sess.GotoNextSourceWithData());
}
sess.EndDataAccess();
#ifndef RTP_SUPPORT_THREAD
status = sess.Poll();
checkerror(status);
#endif // RTP_SUPPORT_THREAD
RTPTime::Wait(RTPTime(1,0));
}
sess.BYEDestroy(RTPTime(10,0),0,0);
#ifdef WIN32
WSACleanup();
#endif // WIN32
return 0;
}

View File

@@ -0,0 +1,101 @@
#include "rtpsession.h"
#include "rtpsessionparams.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtptimeutilities.h"
#include "rtppacket.h"
#include <stdlib.h>
#include <iostream>
using namespace jrtplib;
int main(void)
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
RTPSession session;
RTPSessionParams sessionparams;
sessionparams.SetOwnTimestampUnit(1.0/8000.0);
RTPUDPv4TransmissionParams transparams;
transparams.SetPortbase(8000);
int status = session.Create(sessionparams,&transparams);
if (status < 0)
{
std::cerr << RTPGetErrorString(status) << std::endl;
exit(-1);
}
uint8_t localip[]={127,0,0,1};
RTPIPv4Address addr(localip,9000);
status = session.AddDestination(addr);
if (status < 0)
{
std::cerr << RTPGetErrorString(status) << std::endl;
exit(-1);
}
session.SetDefaultPayloadType(96);
session.SetDefaultMark(false);
session.SetDefaultTimestampIncrement(160);
uint8_t silencebuffer[160];
for (int i = 0 ; i < 160 ; i++)
silencebuffer[i] = 128;
RTPTime delay(0.020);
RTPTime starttime = RTPTime::CurrentTime();
bool done = false;
while (!done)
{
status = session.SendPacket(silencebuffer,160);
if (status < 0)
{
std::cerr << RTPGetErrorString(status) << std::endl;
exit(-1);
}
session.BeginDataAccess();
if (session.GotoFirstSource())
{
do
{
RTPPacket *packet;
while ((packet = session.GetNextPacket()) != 0)
{
std::cout << "Got packet with "
<< "extended sequence number "
<< packet->GetExtendedSequenceNumber()
<< " from SSRC " << packet->GetSSRC()
<< std::endl;
session.DeletePacket(packet);
}
} while (session.GotoNextSource());
}
session.EndDataAccess();
RTPTime::Wait(delay);
RTPTime t = RTPTime::CurrentTime();
t -= starttime;
if (t > RTPTime(60.0))
done = true;
}
delay = RTPTime(10.0);
session.BYEDestroy(delay,"Time's up",9);
#ifdef WIN32
WSACleanup();
#endif // WIN32
return 0;
}

View File

@@ -0,0 +1,225 @@
/*
This IPv4 example listens for incoming packets and automatically adds destinations
for new sources.
*/
#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#ifndef WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif // WIN32
#include "rtpsourcedata.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace jrtplib;
//
// This function checks if there was a RTP error. If so, it displays an error
// message and exists.
//
void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}
//
// The new class routine
//
class MyRTPSession : public RTPSession
{
protected:
void OnNewSource(RTPSourceData *dat)
{
if (dat->IsOwnSSRC())
return;
uint32_t ip;
uint16_t port;
if (dat->GetRTPDataAddress() != 0)
{
const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());
ip = addr->GetIP();
port = addr->GetPort();
}
else if (dat->GetRTCPDataAddress() != 0)
{
const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());
ip = addr->GetIP();
port = addr->GetPort()-1;
}
else
return;
RTPIPv4Address dest(ip,port);
AddDestination(dest);
struct in_addr inaddr;
inaddr.s_addr = htonl(ip);
std::cout << "Adding destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl;
}
void OnBYEPacket(RTPSourceData *dat)
{
if (dat->IsOwnSSRC())
return;
uint32_t ip;
uint16_t port;
if (dat->GetRTPDataAddress() != 0)
{
const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());
ip = addr->GetIP();
port = addr->GetPort();
}
else if (dat->GetRTCPDataAddress() != 0)
{
const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());
ip = addr->GetIP();
port = addr->GetPort()-1;
}
else
return;
RTPIPv4Address dest(ip,port);
DeleteDestination(dest);
struct in_addr inaddr;
inaddr.s_addr = htonl(ip);
std::cout << "Deleting destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl;
}
void OnRemoveSource(RTPSourceData *dat)
{
if (dat->IsOwnSSRC())
return;
if (dat->ReceivedBYE())
return;
uint32_t ip;
uint16_t port;
if (dat->GetRTPDataAddress() != 0)
{
const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());
ip = addr->GetIP();
port = addr->GetPort();
}
else if (dat->GetRTCPDataAddress() != 0)
{
const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());
ip = addr->GetIP();
port = addr->GetPort()-1;
}
else
return;
RTPIPv4Address dest(ip,port);
DeleteDestination(dest);
struct in_addr inaddr;
inaddr.s_addr = htonl(ip);
std::cout << "Deleting destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl;
}
};
//
// The main routine
//
int main(void)
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
MyRTPSession sess;
uint16_t portbase;
std::string ipstr;
int status,i,num;
// First, we'll ask for the necessary information
std::cout << "Enter local portbase:" << std::endl;
std::cin >> portbase;
std::cout << std::endl;
std::cout << std::endl;
std::cout << "Number of seconds you wish to wait:" << std::endl;
std::cin >> num;
// Now, we'll create a RTP session, set the destination
// and poll for incoming data.
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
// IMPORTANT: The local timestamp unit MUST be set, otherwise
// RTCP Sender Report info will be calculated wrong
// In this case, we'll be just use 8000 samples per second.
sessparams.SetOwnTimestampUnit(1.0/8000.0);
sessparams.SetAcceptOwnPackets(true);
transparams.SetPortbase(portbase);
status = sess.Create(sessparams,&transparams);
checkerror(status);
for (i = 1 ; i <= num ; i++)
{
sess.BeginDataAccess();
// check incoming packets
if (sess.GotoFirstSourceWithData())
{
do
{
RTPPacket *pack;
while ((pack = sess.GetNextPacket()) != NULL)
{
// You can examine the data here
printf("Got packet !\n");
// we don't longer need the packet, so
// we'll delete it
sess.DeletePacket(pack);
}
} while (sess.GotoNextSourceWithData());
}
sess.EndDataAccess();
#ifndef RTP_SUPPORT_THREAD
status = sess.Poll();
checkerror(status);
#endif // RTP_SUPPORT_THREAD
RTPTime::Wait(RTPTime(1,0));
}
sess.BYEDestroy(RTPTime(10,0),0,0);
#ifdef WIN32
WSACleanup();
#endif // WIN32
return 0;
}

View File

@@ -0,0 +1,146 @@
/*
This IPv4 example uses the background thread itself to process all packets.
You can use example one to send data to the session that's created in this
example.
*/
#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#ifndef WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif // WIN32
#include "rtpsourcedata.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace jrtplib;
#ifdef RTP_SUPPORT_THREAD
//
// This function checks if there was a RTP error. If so, it displays an error
// message and exists.
//
void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}
//
// The new class routine
//
class MyRTPSession : public RTPSession
{
protected:
void OnPollThreadStep();
void ProcessRTPPacket(const RTPSourceData &srcdat,const RTPPacket &rtppack);
};
void MyRTPSession::OnPollThreadStep()
{
BeginDataAccess();
// check incoming packets
if (GotoFirstSourceWithData())
{
do
{
RTPPacket *pack;
RTPSourceData *srcdat;
srcdat = GetCurrentSourceInfo();
while ((pack = GetNextPacket()) != NULL)
{
ProcessRTPPacket(*srcdat,*pack);
DeletePacket(pack);
}
} while (GotoNextSourceWithData());
}
EndDataAccess();
}
void MyRTPSession::ProcessRTPPacket(const RTPSourceData &srcdat,const RTPPacket &rtppack)
{
// You can inspect the packet and the source's info here
std::cout << "Got packet " << rtppack.GetExtendedSequenceNumber() << " from SSRC " << srcdat.GetSSRC() << std::endl;
}
//
// The main routine
//
int main(void)
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
MyRTPSession sess;
uint16_t portbase;
std::string ipstr;
int status,num;
// First, we'll ask for the necessary information
std::cout << "Enter local portbase:" << std::endl;
std::cin >> portbase;
std::cout << std::endl;
std::cout << std::endl;
std::cout << "Number of seconds you wish to wait:" << std::endl;
std::cin >> num;
// Now, we'll create a RTP session, set the destination
// and poll for incoming data.
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
// IMPORTANT: The local timestamp unit MUST be set, otherwise
// RTCP Sender Report info will be calculated wrong
// In this case, we'll be just use 8000 samples per second.
sessparams.SetOwnTimestampUnit(1.0/8000.0);
transparams.SetPortbase(portbase);
status = sess.Create(sessparams,&transparams);
checkerror(status);
// Wait a number of seconds
RTPTime::Wait(RTPTime(num,0));
sess.BYEDestroy(RTPTime(10,0),0,0);
#ifdef WIN32
WSACleanup();
#endif // WIN32
return 0;
}
#else
int main(void)
{
std::cerr << "Thread support is required for this example" << std::endl;
return 0;
}
#endif // RTP_SUPPORT_THREAD

View File

@@ -0,0 +1,227 @@
/*
This is a modified version of example1.cpp to illustrate the use of a memory
manager.
*/
#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "rtpmemorymanager.h"
#ifndef WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif // WIN32
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace jrtplib;
//
// This function checks if there was a RTP error. If so, it displays an error
// message and exists.
//
void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}
//
// The main routine
//
#ifdef RTP_SUPPORT_THREAD
using namespace jthread;
class MyMemoryManager : public RTPMemoryManager
{
public:
MyMemoryManager()
{
mutex.Init();
alloccount = 0;
freecount = 0;
}
~MyMemoryManager()
{
std::cout << "alloc: " << alloccount << " free: " << freecount << std::endl;
}
void *AllocateBuffer(size_t numbytes, int memtype)
{
mutex.Lock();
void *buf = malloc(numbytes);
std::cout << "Allocated " << numbytes << " bytes at location " << buf << " (memtype = " << memtype << ")" << std::endl;
alloccount++;
mutex.Unlock();
return buf;
}
void FreeBuffer(void *p)
{
mutex.Lock();
std::cout << "Freeing block " << p << std::endl;
freecount++;
free(p);
mutex.Unlock();
}
private:
int alloccount,freecount;
JMutex mutex;
};
#else
class MyMemoryManager : public RTPMemoryManager
{
public:
MyMemoryManager()
{
alloccount = 0;
freecount = 0;
}
~MyMemoryManager()
{
std::cout << "alloc: " << alloccount << " free: " << freecount << std::endl;
}
void *AllocateBuffer(size_t numbytes, int memtype)
{
void *buf = malloc(numbytes);
std::cout << "Allocated " << numbytes << " bytes at location " << buf << " (memtype = " << memtype << ")" << std::endl;
alloccount++;
return buf;
}
void FreeBuffer(void *p)
{
std::cout << "Freeing block " << p << std::endl;
freecount++;
free(p);
}
private:
int alloccount,freecount;
};
#endif // RTP_SUPPORT_THREAD
int main(void)
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
MyMemoryManager mgr;
RTPSession sess(0, &mgr);
uint16_t portbase,destport;
uint32_t destip;
std::string ipstr;
int status,i,num;
// First, we'll ask for the necessary information
std::cout << "Enter local portbase:" << std::endl;
std::cin >> portbase;
std::cout << std::endl;
std::cout << "Enter the destination IP address" << std::endl;
std::cin >> ipstr;
destip = inet_addr(ipstr.c_str());
if (destip == INADDR_NONE)
{
std::cerr << "Bad IP address specified" << std::endl;
return -1;
}
// The inet_addr function returns a value in network byte order, but
// we need the IP address in host byte order, so we use a call to
// ntohl
destip = ntohl(destip);
std::cout << "Enter the destination port" << std::endl;
std::cin >> destport;
std::cout << std::endl;
std::cout << "Number of packets you wish to be sent:" << std::endl;
std::cin >> num;
// Now, we'll create a RTP session, set the destination, send some
// packets and poll for incoming data.
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
// IMPORTANT: The local timestamp unit MUST be set, otherwise
// RTCP Sender Report info will be calculated wrong
// In this case, we'll be sending 10 samples each second, so we'll
// put the timestamp unit to (1.0/10.0)
sessparams.SetOwnTimestampUnit(1.0/10.0);
sessparams.SetAcceptOwnPackets(true);
transparams.SetPortbase(portbase);
status = sess.Create(sessparams,&transparams);
checkerror(status);
RTPIPv4Address addr(destip,destport);
status = sess.AddDestination(addr);
checkerror(status);
for (i = 1 ; i <= num ; i++)
{
printf("\nSending packet %d/%d\n",i,num);
// send the packet
status = sess.SendPacket((void *)"1234567890",10,0,false,10);
checkerror(status);
sess.BeginDataAccess();
// check incoming packets
if (sess.GotoFirstSourceWithData())
{
do
{
RTPPacket *pack;
while ((pack = sess.GetNextPacket()) != NULL)
{
// You can examine the data here
printf("Got packet !\n");
// we don't longer need the packet, so
// we'll delete it
sess.DeletePacket(pack);
}
} while (sess.GotoNextSourceWithData());
}
sess.EndDataAccess();
#ifndef RTP_SUPPORT_THREAD
status = sess.Poll();
checkerror(status);
#endif // RTP_SUPPORT_THREAD
RTPTime::Wait(RTPTime(1,0));
}
sess.BYEDestroy(RTPTime(10,0),0,0);
#ifdef WIN32
WSACleanup();
#endif // WIN32
return 0;
}

View File

@@ -0,0 +1,488 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="jrtplib"
ProjectGUID="{D39837A7-419F-4751-A090-429F4D3B0038}"
RootNamespace="jrtplib"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
WholeProgramOptimization="false"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
TreatWChar_tAsBuiltInType="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\src\rtcpapppacket.cpp"
>
</File>
<File
RelativePath=".\src\rtcpapppacket.h"
>
</File>
<File
RelativePath=".\src\rtcpbyepacket.cpp"
>
</File>
<File
RelativePath=".\src\rtcpbyepacket.h"
>
</File>
<File
RelativePath=".\src\rtcpcompoundpacket.cpp"
>
</File>
<File
RelativePath=".\src\rtcpcompoundpacket.h"
>
</File>
<File
RelativePath=".\src\rtcpcompoundpacketbuilder.cpp"
>
</File>
<File
RelativePath=".\src\rtcpcompoundpacketbuilder.h"
>
</File>
<File
RelativePath=".\src\rtcppacket.cpp"
>
</File>
<File
RelativePath=".\src\rtcppacket.h"
>
</File>
<File
RelativePath=".\src\rtcppacketbuilder.cpp"
>
</File>
<File
RelativePath=".\src\rtcppacketbuilder.h"
>
</File>
<File
RelativePath=".\src\rtcprrpacket.cpp"
>
</File>
<File
RelativePath=".\src\rtcprrpacket.h"
>
</File>
<File
RelativePath=".\src\rtcpscheduler.cpp"
>
</File>
<File
RelativePath=".\src\rtcpscheduler.h"
>
</File>
<File
RelativePath=".\src\rtcpsdesinfo.cpp"
>
</File>
<File
RelativePath=".\src\rtcpsdesinfo.h"
>
</File>
<File
RelativePath=".\src\rtcpsdespacket.cpp"
>
</File>
<File
RelativePath=".\src\rtcpsdespacket.h"
>
</File>
<File
RelativePath=".\src\rtcpsrpacket.cpp"
>
</File>
<File
RelativePath=".\src\rtcpsrpacket.h"
>
</File>
<File
RelativePath=".\src\rtcpunknownpacket.h"
>
</File>
<File
RelativePath=".\src\rtpaddress.h"
>
</File>
<File
RelativePath=".\src\rtpbyteaddress.cpp"
>
</File>
<File
RelativePath=".\src\rtpbyteaddress.h"
>
</File>
<File
RelativePath=".\src\rtpcollisionlist.cpp"
>
</File>
<File
RelativePath=".\src\rtpcollisionlist.h"
>
</File>
<File
RelativePath=".\src\rtpconfig.h"
>
</File>
<File
RelativePath=".\src\rtpdebug.cpp"
>
</File>
<File
RelativePath=".\src\rtpdebug.h"
>
</File>
<File
RelativePath=".\src\rtpdefines.h"
>
</File>
<File
RelativePath=".\src\rtperrors.cpp"
>
</File>
<File
RelativePath=".\src\rtperrors.h"
>
</File>
<File
RelativePath=".\src\rtpexternaltransmitter.cpp"
>
</File>
<File
RelativePath=".\src\rtpexternaltransmitter.h"
>
</File>
<File
RelativePath=".\src\rtphashtable.h"
>
</File>
<File
RelativePath=".\src\rtpinternalsourcedata.cpp"
>
</File>
<File
RelativePath=".\src\rtpinternalsourcedata.h"
>
</File>
<File
RelativePath=".\src\rtpipv4address.cpp"
>
</File>
<File
RelativePath=".\src\rtpipv4address.h"
>
</File>
<File
RelativePath=".\src\rtpipv4destination.h"
>
</File>
<File
RelativePath=".\src\rtpipv6address.cpp"
>
</File>
<File
RelativePath=".\src\rtpipv6address.h"
>
</File>
<File
RelativePath=".\src\rtpipv6destination.h"
>
</File>
<File
RelativePath=".\src\rtpkeyhashtable.h"
>
</File>
<File
RelativePath=".\src\rtplibraryversion.cpp"
>
</File>
<File
RelativePath=".\src\rtplibraryversion.h"
>
</File>
<File
RelativePath=".\src\rtpmemorymanager.h"
>
</File>
<File
RelativePath=".\src\rtpmemoryobject.h"
>
</File>
<File
RelativePath=".\src\rtppacket.cpp"
>
</File>
<File
RelativePath=".\src\rtppacket.h"
>
</File>
<File
RelativePath=".\src\rtppacketbuilder.cpp"
>
</File>
<File
RelativePath=".\src\rtppacketbuilder.h"
>
</File>
<File
RelativePath=".\src\rtppollthread.cpp"
>
</File>
<File
RelativePath=".\src\rtppollthread.h"
>
</File>
<File
RelativePath=".\src\rtprandom.cpp"
>
</File>
<File
RelativePath=".\src\rtprandom.h"
>
</File>
<File
RelativePath=".\src\rtprandomrand48.cpp"
>
</File>
<File
RelativePath=".\src\rtprandomrand48.h"
>
</File>
<File
RelativePath=".\src\rtprandomrands.cpp"
>
</File>
<File
RelativePath=".\src\rtprandomrands.h"
>
</File>
<File
RelativePath=".\src\rtprandomurandom.cpp"
>
</File>
<File
RelativePath=".\src\rtprandomurandom.h"
>
</File>
<File
RelativePath=".\src\rtprawpacket.h"
>
</File>
<File
RelativePath=".\src\rtpsession.cpp"
>
</File>
<File
RelativePath=".\src\rtpsession.h"
>
</File>
<File
RelativePath=".\src\rtpsessionparams.cpp"
>
</File>
<File
RelativePath=".\src\rtpsessionparams.h"
>
</File>
<File
RelativePath=".\src\rtpsessionsources.cpp"
>
</File>
<File
RelativePath=".\src\rtpsessionsources.h"
>
</File>
<File
RelativePath=".\src\rtpsourcedata.cpp"
>
</File>
<File
RelativePath=".\src\rtpsourcedata.h"
>
</File>
<File
RelativePath=".\src\rtpsources.cpp"
>
</File>
<File
RelativePath=".\src\rtpsources.h"
>
</File>
<File
RelativePath=".\src\rtpstructs.h"
>
</File>
<File
RelativePath=".\src\rtptimeutilities.cpp"
>
</File>
<File
RelativePath=".\src\rtptimeutilities.h"
>
</File>
<File
RelativePath=".\src\rtptransmitter.h"
>
</File>
<File
RelativePath=".\src\rtptypes_win.h"
>
</File>
<File
RelativePath=".\src\rtpudpv4transmitter.cpp"
>
</File>
<File
RelativePath=".\src\rtpudpv4transmitter.h"
>
</File>
<File
RelativePath=".\src\rtpudpv6transmitter.cpp"
>
</File>
<File
RelativePath=".\src\rtpudpv6transmitter.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D39837A7-419F-4751-A090-429F4D3B0038}</ProjectGuid>
<RootNamespace>jrtplib</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>12.0.21005.1</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\rtcpapppacket.cpp" />
<ClCompile Include="src\rtcpbyepacket.cpp" />
<ClCompile Include="src\rtcpcompoundpacket.cpp" />
<ClCompile Include="src\rtcpcompoundpacketbuilder.cpp" />
<ClCompile Include="src\rtcppacket.cpp" />
<ClCompile Include="src\rtcppacketbuilder.cpp" />
<ClCompile Include="src\rtcprrpacket.cpp" />
<ClCompile Include="src\rtcpscheduler.cpp" />
<ClCompile Include="src\rtcpsdesinfo.cpp" />
<ClCompile Include="src\rtcpsdespacket.cpp" />
<ClCompile Include="src\rtcpsrpacket.cpp" />
<ClCompile Include="src\rtpbyteaddress.cpp" />
<ClCompile Include="src\rtpcollisionlist.cpp" />
<ClCompile Include="src\rtpdebug.cpp" />
<ClCompile Include="src\rtperrors.cpp" />
<ClCompile Include="src\rtpexternaltransmitter.cpp" />
<ClCompile Include="src\rtpinternalsourcedata.cpp" />
<ClCompile Include="src\rtpipv4address.cpp" />
<ClCompile Include="src\rtpipv6address.cpp" />
<ClCompile Include="src\rtplibraryversion.cpp" />
<ClCompile Include="src\rtppacket.cpp" />
<ClCompile Include="src\rtppacketbuilder.cpp" />
<ClCompile Include="src\rtppollthread.cpp" />
<ClCompile Include="src\rtprandom.cpp" />
<ClCompile Include="src\rtprandomrand48.cpp" />
<ClCompile Include="src\rtprandomrands.cpp" />
<ClCompile Include="src\rtprandomurandom.cpp" />
<ClCompile Include="src\rtpsession.cpp" />
<ClCompile Include="src\rtpsessionparams.cpp" />
<ClCompile Include="src\rtpsessionsources.cpp" />
<ClCompile Include="src\rtpsourcedata.cpp" />
<ClCompile Include="src\rtpsources.cpp" />
<ClCompile Include="src\rtptimeutilities.cpp" />
<ClCompile Include="src\rtpudpv4transmitter.cpp" />
<ClCompile Include="src\rtpudpv6transmitter.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\rtcpapppacket.h" />
<ClInclude Include="src\rtcpbyepacket.h" />
<ClInclude Include="src\rtcpcompoundpacket.h" />
<ClInclude Include="src\rtcpcompoundpacketbuilder.h" />
<ClInclude Include="src\rtcppacket.h" />
<ClInclude Include="src\rtcppacketbuilder.h" />
<ClInclude Include="src\rtcprrpacket.h" />
<ClInclude Include="src\rtcpscheduler.h" />
<ClInclude Include="src\rtcpsdesinfo.h" />
<ClInclude Include="src\rtcpsdespacket.h" />
<ClInclude Include="src\rtcpsrpacket.h" />
<ClInclude Include="src\rtcpunknownpacket.h" />
<ClInclude Include="src\rtpaddress.h" />
<ClInclude Include="src\rtpbyteaddress.h" />
<ClInclude Include="src\rtpcollisionlist.h" />
<ClInclude Include="src\rtpconfig.h" />
<ClInclude Include="src\rtpdebug.h" />
<ClInclude Include="src\rtpdefines.h" />
<ClInclude Include="src\rtperrors.h" />
<ClInclude Include="src\rtpexternaltransmitter.h" />
<ClInclude Include="src\rtphashtable.h" />
<ClInclude Include="src\rtpinternalsourcedata.h" />
<ClInclude Include="src\rtpipv4address.h" />
<ClInclude Include="src\rtpipv4destination.h" />
<ClInclude Include="src\rtpipv6address.h" />
<ClInclude Include="src\rtpipv6destination.h" />
<ClInclude Include="src\rtpkeyhashtable.h" />
<ClInclude Include="src\rtplibraryversion.h" />
<ClInclude Include="src\rtpmemorymanager.h" />
<ClInclude Include="src\rtpmemoryobject.h" />
<ClInclude Include="src\rtppacket.h" />
<ClInclude Include="src\rtppacketbuilder.h" />
<ClInclude Include="src\rtppollthread.h" />
<ClInclude Include="src\rtprandom.h" />
<ClInclude Include="src\rtprandomrand48.h" />
<ClInclude Include="src\rtprandomrands.h" />
<ClInclude Include="src\rtprandomurandom.h" />
<ClInclude Include="src\rtprawpacket.h" />
<ClInclude Include="src\rtpsession.h" />
<ClInclude Include="src\rtpsessionparams.h" />
<ClInclude Include="src\rtpsessionsources.h" />
<ClInclude Include="src\rtpsourcedata.h" />
<ClInclude Include="src\rtpsources.h" />
<ClInclude Include="src\rtpstructs.h" />
<ClInclude Include="src\rtptimeutilities.h" />
<ClInclude Include="src\rtptransmitter.h" />
<ClInclude Include="src\rtptypes_win.h" />
<ClInclude Include="src\rtpudpv4transmitter.h" />
<ClInclude Include="src\rtpudpv6transmitter.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@@ -0,0 +1,6 @@
Name: Jrtplib
Description: A full featured RTP library
Requires:
Version: ${VERSION}
Libs: ${JRTPLIB_LIBS_PKGCONFIG}
Cflags: ${JRTPLIB_INCDIRS_PKGCONFIG}

View File

@@ -0,0 +1,93 @@
add_definitions(-DJRTPLIB_COMPILING)
set (JRTPLIB_HEADERS
rtcpapppacket.h
rtcpbyepacket.h
rtcpcompoundpacket.h
rtcpcompoundpacketbuilder.h
rtcppacket.h
rtcppacketbuilder.h
rtcprrpacket.h
rtcpscheduler.h
rtcpsdesinfo.h
rtcpsdespacket.h
rtcpsrpacket.h
rtcpunknownpacket.h
rtpaddress.h
rtpcollisionlist.h
${PROJECT_BINARY_DIR}/src/rtpconfig.h
rtpdebug.h
rtpdefines.h
rtperrors.h
rtphashtable.h
rtpinternalsourcedata.h
rtpipv4address.h
rtpipv4destination.h
rtpipv6address.h
rtpipv6destination.h
rtpkeyhashtable.h
rtplibraryversion.h
rtpmemorymanager.h
rtpmemoryobject.h
rtppacket.h
rtppacketbuilder.h
rtppollthread.h
rtprandom.h
rtprandomrand48.h
rtprandomrands.h
rtprandomurandom.h
rtprawpacket.h
rtpsession.h
rtpsessionparams.h
rtpsessionsources.h
rtpsourcedata.h
rtpsources.h
rtpstructs.h
rtptimeutilities.h
rtptransmitter.h
rtptypes_win.h
${PROJECT_BINARY_DIR}/src/rtptypes.h
rtpudpv4transmitter.h
rtpudpv6transmitter.h
rtpbyteaddress.h
rtpexternaltransmitter.h)
set(JRTPLIB_SOURCES
rtcpapppacket.cpp
rtcpbyepacket.cpp
rtcpcompoundpacket.cpp
rtcpcompoundpacketbuilder.cpp
rtcppacket.cpp
rtcppacketbuilder.cpp
rtcprrpacket.cpp
rtcpscheduler.cpp
rtcpsdesinfo.cpp
rtcpsdespacket.cpp
rtcpsrpacket.cpp
rtpcollisionlist.cpp
rtpdebug.cpp
rtperrors.cpp
rtpinternalsourcedata.cpp
rtpipv4address.cpp
rtpipv6address.cpp
rtplibraryversion.cpp
rtppacket.cpp
rtppacketbuilder.cpp
rtppollthread.cpp
rtprandom.cpp
rtprandomrand48.cpp
rtprandomrands.cpp
rtprandomurandom.cpp
rtpsession.cpp
rtpsessionparams.cpp
rtpsessionsources.cpp
rtpsourcedata.cpp
rtpsources.cpp
rtptimeutilities.cpp
rtpudpv4transmitter.cpp
rtpudpv6transmitter.cpp
rtpbyteaddress.cpp
rtpexternaltransmitter.cpp)
add_library(jrtplib STATIC ${JRTPLIB_SOURCES})

View File

@@ -0,0 +1,2 @@
#!/bin/bash
for i in `cat rtperrors.h | cut -f 2 -d " " | cut -f 1 |grep -e "^ERR"`; do echo $i ; BLA=`grep $i *.cpp *.h|cut -f 1 -d ":"|sort|uniq`; if [ "BLA$BLA" != BLA ] ; then for j in $BLA ; do if [ $j != "rtperrors.h" ] ; then echo -e "\t$j" ; fi ; done ; fi ;done

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,247 @@
/*
This class allows for jrtp to process packets without sending them out
anywhere.
The incoming messages are handed in to jrtp through the TransmissionParams
and can be retreived from jrtp through the normal polling mecanisms.
The outgoing RTP/RTCP packets are given to jrtp through the normal
session->SendPacket() and those packets are handed back out to the
client through a callback function (packet_ready_cb).
example usage : Allows for integration of RTP into gstreamer.
Copyright (c) 2005 Philippe Khalaf <burger@speedy.org>
This file is a part of JRTPLIB
Copyright (c) 1999-2004 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the "Expertisecentrum Digitale Media"
(http://www.edm.luc.ac.be), a research center of the "Limburgs Universitair
Centrum" (http://www.luc.ac.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPFAKETRANSMITTER_H
#define RTPFAKETRANSMITTER_H
#include "rtpconfig.h"
#include "rtptransmitter.h"
#include "rtpipv4destination.h"
#include "rtphashtable.h"
#include "rtpkeyhashtable.h"
#include <list>
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jmutex.h>
#endif // RTP_SUPPORT_THREAD
#define RTPFAKETRANS_HASHSIZE 8317
#define RTPFAKETRANS_DEFAULTPORTBASE 5000
namespace jrtplib
{
// Definition of a callback that is called when a packet is ready for sending
// params (*data, data_len, dest_addr, dest_port, rtp [1 if rtp, 0 if rtcp])
typedef void(*packet_ready_cb)(void*, uint8_t*, uint16_t, uint32_t, uint16_t, int rtp);
class RTPFakeTransmissionParams : public RTPTransmissionParams
{
public:
RTPFakeTransmissionParams():RTPTransmissionParams(RTPTransmitter::UserDefinedProto) { portbase = RTPFAKETRANS_DEFAULTPORTBASE; bindIP = 0; multicastTTL = 1; currentdata = NULL;}
void SetBindIP(uint32_t ip) { bindIP = ip; }
void SetPortbase(uint16_t pbase) { portbase = pbase; }
void SetMulticastTTL(uint8_t mcastTTL) { multicastTTL = mcastTTL; }
void SetLocalIPList(std::list<uint32_t> &iplist) { localIPs = iplist; }
void ClearLocalIPList() { localIPs.clear(); }
void SetCurrentData(uint8_t *data) { currentdata = data; }
void SetCurrentDataLen(uint16_t len) { currentdatalen = len; }
void SetCurrentDataAddr(uint32_t addr) { currentdataaddr = addr; }
void SetCurrentDataPort(uint16_t port) { currentdataport = port; }
void SetCurrentDataType(bool type) { currentdatatype = type; }
void SetPacketReadyCB(packet_ready_cb cb) { packetreadycb = cb; };
void SetPacketReadyCBData(void *data) { packetreadycbdata = data; };
uint32_t GetBindIP() const { return bindIP; }
uint16_t GetPortbase() const { return portbase; }
uint8_t GetMulticastTTL() const { return multicastTTL; }
const std::list<uint32_t> &GetLocalIPList() const { return localIPs; }
uint8_t* GetCurrentData() const { return currentdata; }
uint16_t GetCurrentDataLen() const { return currentdatalen; }
uint32_t GetCurrentDataAddr() const { return currentdataaddr; }
uint16_t GetCurrentDataPort() const { return currentdataport; }
bool GetCurrentDataType() const { return currentdatatype; }
packet_ready_cb GetPacketReadyCB() const { return packetreadycb; }
void* GetPacketReadyCBData() const { return packetreadycbdata; }
private:
uint16_t portbase;
uint32_t bindIP;
std::list<uint32_t> localIPs;
uint8_t multicastTTL;
uint8_t* currentdata;
uint16_t currentdatalen;
uint32_t currentdataaddr;
uint16_t currentdataport;
bool currentdatatype;
packet_ready_cb packetreadycb;
void *packetreadycbdata;
};
class RTPFakeTransmissionInfo : public RTPTransmissionInfo
{
public:
RTPFakeTransmissionInfo(std::list<uint32_t> iplist,
RTPFakeTransmissionParams *transparams) :
RTPTransmissionInfo(RTPTransmitter::UserDefinedProto)
{ localIPlist = iplist; params = transparams; }
~RTPFakeTransmissionInfo() { }
std::list<uint32_t> GetLocalIPList() const { return localIPlist; }
RTPFakeTransmissionParams* GetTransParams() { return params; }
private:
std::list<uint32_t> localIPlist;
RTPFakeTransmissionParams *params;
};
class RTPFakeTrans_GetHashIndex_IPv4Dest
{
public:
static int GetIndex(const RTPIPv4Destination &d) { return d.GetIP()%RTPFAKETRANS_HASHSIZE; }
};
class RTPFakeTrans_GetHashIndex_uint32_t
{
public:
static int GetIndex(const uint32_t &k) { return k%RTPFAKETRANS_HASHSIZE; }
};
#define RTPFAKETRANS_HEADERSIZE (20+8)
class RTPFakeTransmitter : public RTPTransmitter
{
public:
RTPFakeTransmitter(RTPMemoryManager *mgr);
~RTPFakeTransmitter();
int Init(bool treadsafe);
int Create(size_t maxpacksize,const RTPTransmissionParams *transparams);
void Destroy();
RTPTransmissionInfo *GetTransmissionInfo();
void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
int GetLocalHostName(uint8_t *buffer,size_t *bufferlength);
bool ComesFromThisTransmitter(const RTPAddress *addr);
size_t GetHeaderOverhead() { return RTPFAKETRANS_HEADERSIZE; }
int Poll();
int WaitForIncomingData(const RTPTime &delay,bool *dataavailable = 0);
int AbortWait();
int SendRTPData(const void *data,size_t len);
int SendRTCPData(const void *data,size_t len);
int AddDestination(const RTPAddress &addr);
int DeleteDestination(const RTPAddress &addr);
void ClearDestinations();
bool SupportsMulticasting();
int JoinMulticastGroup(const RTPAddress &addr);
int LeaveMulticastGroup(const RTPAddress &addr);
void LeaveAllMulticastGroups();
int SetReceiveMode(RTPTransmitter::ReceiveMode m);
int AddToIgnoreList(const RTPAddress &addr);
int DeleteFromIgnoreList(const RTPAddress &addr);
void ClearIgnoreList();
int AddToAcceptList(const RTPAddress &addr);
int DeleteFromAcceptList(const RTPAddress &addr);
void ClearAcceptList();
int SetMaximumPacketSize(size_t s);
bool NewDataAvailable();
RTPRawPacket *GetNextPacket();
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
private:
int CreateLocalIPList();
bool GetLocalIPList_Interfaces();
void GetLocalIPList_DNS();
void AddLoopbackAddress();
void FlushPackets();
int FakePoll();
int ProcessAddAcceptIgnoreEntry(uint32_t ip,uint16_t port);
int ProcessDeleteAcceptIgnoreEntry(uint32_t ip,uint16_t port);
#ifdef RTP_SUPPORT_IPV4MULTICAST
bool SetMulticastTTL(uint8_t ttl);
#endif // RTP_SUPPORT_IPV4MULTICAST
bool ShouldAcceptData(uint32_t srcip,uint16_t srcport);
void ClearAcceptIgnoreInfo();
RTPFakeTransmissionParams *params;
bool init;
bool created;
bool waitingfordata;
std::list<uint32_t> localIPs;
uint16_t portbase;
uint8_t multicastTTL;
RTPTransmitter::ReceiveMode receivemode;
uint8_t *localhostname;
size_t localhostnamelength;
RTPHashTable<const RTPIPv4Destination,RTPFakeTrans_GetHashIndex_IPv4Dest,RTPFAKETRANS_HASHSIZE> destinations;
#ifdef RTP_SUPPORT_IPV4MULTICAST
// RTPHashTable<const uint32_t,RTPFakeTrans_GetHashIndex_uint32_t,RTPFAKETRANS_HASHSIZE> multicastgroups;
#endif // RTP_SUPPORT_IPV4MULTICAST
std::list<RTPRawPacket*> rawpacketlist;
bool supportsmulticasting;
size_t maxpacksize;
class PortInfo
{
public:
PortInfo() { all = false; }
bool all;
std::list<uint16_t> portlist;
};
RTPKeyHashTable<const uint32_t,PortInfo*,RTPFakeTrans_GetHashIndex_uint32_t,RTPFAKETRANS_HASHSIZE> acceptignoreinfo;
int CreateAbortDescriptors();
void DestroyAbortDescriptors();
void AbortWaitInternal();
#ifdef RTP_SUPPORT_THREAD
jthread::JMutex mainmutex,waitmutex;
int threadsafe;
#endif // RTP_SUPPORT_THREAD
};
} // end namespace
#endif // RTPFAKETRANSMITTER_H

View File

@@ -0,0 +1,93 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpapppacket.h"
#ifdef RTPDEBUG
#include <string.h>
#include <iostream>
#include <string>
#endif // RTPDEBUG
#include "rtpdebug.h"
namespace jrtplib
{
RTCPAPPPacket::RTCPAPPPacket(uint8_t *data,size_t datalength)
: RTCPPacket(APP,data,datalength)
{
knownformat = false;
RTCPCommonHeader *hdr;
size_t len = datalength;
hdr = (RTCPCommonHeader *)data;
if (hdr->padding)
{
uint8_t padcount = data[datalength-1];
if ((padcount & 0x03) != 0) // not a multiple of four! (see rfc 3550 p 37)
return;
if (((size_t)padcount) >= len)
return;
len -= (size_t)padcount;
}
if (len < (sizeof(RTCPCommonHeader)+sizeof(uint32_t)*2))
return;
len -= (sizeof(RTCPCommonHeader)+sizeof(uint32_t)*2);
appdatalen = len;
knownformat = true;
}
#ifdef RTPDEBUG
void RTCPAPPPacket::Dump()
{
RTCPPacket::Dump();
if (!IsKnownFormat())
{
std::cout << " Unknown format!" << std::endl;
}
else
{
std::cout << " SSRC: " << GetSSRC() << std::endl;
char str[5];
memcpy(str,GetName(),4);
str[4] = 0;
std::cout << " Name: " << std::string(str).c_str() << std::endl;
std::cout << " Length: " << GetAPPDataLength() << std::endl;
}
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,132 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpapppacket.h
*/
#ifndef RTCPAPPPACKET_H
#define RTCPAPPPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
#include "rtpstructs.h"
#if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h>
#endif // WIN32
namespace jrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP APP packet. */
class JRTPLIB_IMPORTEXPORT RTCPAPPPacket : public RTCPPacket
{
public:
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it
* points to is valid as long as the class instance exists.
*/
RTCPAPPPacket(uint8_t *data,size_t datalen);
~RTCPAPPPacket() { }
/** Returns the subtype contained in the APP packet. */
uint8_t GetSubType() const;
/** Returns the SSRC of the source which sent this packet. */
uint32_t GetSSRC() const;
/** Returns the name contained in the APP packet.
* Returns the name contained in the APP packet. This alway consists of four bytes and is not NULL-terminated.
*/
uint8_t *GetName();
/** Returns a pointer to the actual data. */
uint8_t *GetAPPData();
/** Returns the length of the actual data. */
size_t GetAPPDataLength() const;
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
private:
size_t appdatalen;
};
inline uint8_t RTCPAPPPacket::GetSubType() const
{
if (!knownformat)
return 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
return hdr->count;
}
inline uint32_t RTCPAPPPacket::GetSSRC() const
{
if (!knownformat)
return 0;
uint32_t *ssrc = (uint32_t *)(data+sizeof(RTCPCommonHeader));
return ntohl(*ssrc);
}
inline uint8_t *RTCPAPPPacket::GetName()
{
if (!knownformat)
return 0;
return (data+sizeof(RTCPCommonHeader)+sizeof(uint32_t));
}
inline uint8_t *RTCPAPPPacket::GetAPPData()
{
if (!knownformat)
return 0;
if (appdatalen == 0)
return 0;
return (data+sizeof(RTCPCommonHeader)+sizeof(uint32_t)*2);
}
inline size_t RTCPAPPPacket::GetAPPDataLength() const
{
if (!knownformat)
return 0;
return appdatalen;
}
} // end namespace
#endif // RTCPAPPPACKET_H

View File

@@ -0,0 +1,104 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpbyepacket.h"
#ifdef RTPDEBUG
#include <iostream>
#include <string.h>
#endif // RTPDEBUG
#include "rtpdebug.h"
namespace jrtplib
{
RTCPBYEPacket::RTCPBYEPacket(uint8_t *data,size_t datalength)
: RTCPPacket(BYE,data,datalength)
{
knownformat = false;
reasonoffset = 0;
RTCPCommonHeader *hdr;
size_t len = datalength;
hdr = (RTCPCommonHeader *)data;
if (hdr->padding)
{
uint8_t padcount = data[datalength-1];
if ((padcount & 0x03) != 0) // not a multiple of four! (see rfc 3550 p 37)
return;
if (((size_t)padcount) >= len)
return;
len -= (size_t)padcount;
}
size_t ssrclen = ((size_t)(hdr->count))*sizeof(uint32_t) + sizeof(RTCPCommonHeader);
if (ssrclen > len)
return;
if (ssrclen < len) // there's probably a reason for leaving
{
uint8_t *reasonlength = (data+ssrclen);
size_t reaslen = (size_t)(*reasonlength);
if (reaslen > (len-ssrclen-1))
return;
reasonoffset = ssrclen;
}
knownformat = true;
}
#ifdef RTPDEBUG
void RTCPBYEPacket::Dump()
{
RTCPPacket::Dump();
if (!IsKnownFormat())
{
std::cout << " Unknown format" << std::endl;
return;
}
int num = GetSSRCCount();
int i;
for (i = 0 ; i < num ; i++)
std::cout << " SSRC: " << GetSSRC(i) << std::endl;
if (HasReasonForLeaving())
{
char str[1024];
memcpy(str,GetReasonData(),GetReasonLength());
str[GetReasonLength()] = 0;
std::cout << " Reason: " << str << std::endl;
}
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,140 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpbyepacket.h
*/
#ifndef RTCPBYEPACKET_H
#define RTCPBYEPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
#include "rtpstructs.h"
#if ! (defined(WIN32) || defined (_WIN32_WCE))
#include <netinet/in.h>
#endif // WIN32
namespace jrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP BYE packet. */
class JRTPLIB_IMPORTEXPORT RTCPBYEPacket : public RTCPPacket
{
public:
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it
* points to is valid as long as the class instance exists.
*/
RTCPBYEPacket(uint8_t *data,size_t datalen);
~RTCPBYEPacket() { }
/** Returns the number of SSRC identifiers present in this BYE packet. */
int GetSSRCCount() const;
/** Returns the SSRC described by \c index which may have a value from 0 to GetSSRCCount()-1
* (note that no check is performed to see if \c index is valid).
*/
uint32_t GetSSRC(int index) const; // note: no check is performed to see if index is valid!
/** Returns true if the BYE packet contains a reason for leaving. */
bool HasReasonForLeaving() const;
/** Returns the length of the string which describes why the source(s) left. */
size_t GetReasonLength() const;
/** Returns the actual reason for leaving data. */
uint8_t *GetReasonData();
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
private:
size_t reasonoffset;
};
inline int RTCPBYEPacket::GetSSRCCount() const
{
if (!knownformat)
return 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
return (int)(hdr->count);
}
inline uint32_t RTCPBYEPacket::GetSSRC(int index) const
{
if (!knownformat)
return 0;
uint32_t *ssrc = (uint32_t *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t)*index);
return ntohl(*ssrc);
}
inline bool RTCPBYEPacket::HasReasonForLeaving() const
{
if (!knownformat)
return false;
if (reasonoffset == 0)
return false;
return true;
}
inline size_t RTCPBYEPacket::GetReasonLength() const
{
if (!knownformat)
return 0;
if (reasonoffset == 0)
return 0;
uint8_t *reasonlen = (data+reasonoffset);
return (size_t)(*reasonlen);
}
inline uint8_t *RTCPBYEPacket::GetReasonData()
{
if (!knownformat)
return 0;
if (reasonoffset == 0)
return 0;
uint8_t *reasonlen = (data+reasonoffset);
if ((*reasonlen) == 0)
return 0;
return (data+reasonoffset+1);
}
} // end namespace
#endif // RTCPBYEPACKET_H

View File

@@ -0,0 +1,232 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpcompoundpacket.h"
#include "rtprawpacket.h"
#include "rtperrors.h"
#include "rtpstructs.h"
#include "rtpdefines.h"
#include "rtcpsrpacket.h"
#include "rtcprrpacket.h"
#include "rtcpsdespacket.h"
#include "rtcpbyepacket.h"
#include "rtcpapppacket.h"
#include "rtcpunknownpacket.h"
#if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h>
#endif // WIN32
#include "rtpdebug.h"
namespace jrtplib
{
RTCPCompoundPacket::RTCPCompoundPacket(RTPRawPacket &rawpack, RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
{
compoundpacket = 0;
compoundpacketlength = 0;
error = 0;
if (rawpack.IsRTP())
{
error = ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
return;
}
uint8_t *data = rawpack.GetData();
size_t datalen = rawpack.GetDataLength();
error = ParseData(data,datalen);
if (error < 0)
return;
compoundpacket = rawpack.GetData();
compoundpacketlength = rawpack.GetDataLength();
deletepacket = true;
rawpack.ZeroData();
rtcppackit = rtcppacklist.begin();
}
RTCPCompoundPacket::RTCPCompoundPacket(uint8_t *packet, size_t packetlen, bool deletedata, RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
{
compoundpacket = 0;
compoundpacketlength = 0;
error = ParseData(packet,packetlen);
if (error < 0)
return;
compoundpacket = packet;
compoundpacketlength = packetlen;
deletepacket = deletedata;
rtcppackit = rtcppacklist.begin();
}
RTCPCompoundPacket::RTCPCompoundPacket(RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
{
compoundpacket = 0;
compoundpacketlength = 0;
error = 0;
deletepacket = true;
}
int RTCPCompoundPacket::ParseData(uint8_t *data, size_t datalen)
{
bool first;
if (datalen < sizeof(RTCPCommonHeader))
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
first = true;
do
{
RTCPCommonHeader *rtcphdr;
size_t length;
rtcphdr = (RTCPCommonHeader *)data;
if (rtcphdr->version != RTP_VERSION) // check version
{
ClearPacketList();
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
}
if (first)
{
// Check if first packet is SR or RR
first = false;
if ( ! (rtcphdr->packettype == RTP_RTCPTYPE_SR || rtcphdr->packettype == RTP_RTCPTYPE_RR))
{
ClearPacketList();
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
}
}
length = (size_t)ntohs(rtcphdr->length);
length++;
length *= sizeof(uint32_t);
if (length > datalen) // invalid length field
{
ClearPacketList();
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
}
if (rtcphdr->padding)
{
// check if it's the last packet
if (length != datalen)
{
ClearPacketList();
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
}
}
RTCPPacket *p;
switch (rtcphdr->packettype)
{
case RTP_RTCPTYPE_SR:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPSRPACKET) RTCPSRPacket(data,length);
break;
case RTP_RTCPTYPE_RR:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPRRPACKET) RTCPRRPacket(data,length);
break;
case RTP_RTCPTYPE_SDES:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPSDESPACKET) RTCPSDESPacket(data,length);
break;
case RTP_RTCPTYPE_BYE:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPBYEPACKET) RTCPBYEPacket(data,length);
break;
case RTP_RTCPTYPE_APP:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPAPPPACKET) RTCPAPPPacket(data,length);
break;
default:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPUNKNOWNPACKET) RTCPUnknownPacket(data,length);
}
if (p == 0)
{
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
datalen -= length;
data += length;
} while (datalen >= (size_t)sizeof(RTCPCommonHeader));
if (datalen != 0) // some remaining bytes
{
ClearPacketList();
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
}
return 0;
}
RTCPCompoundPacket::~RTCPCompoundPacket()
{
ClearPacketList();
if (compoundpacket && deletepacket)
RTPDeleteByteArray(compoundpacket,GetMemoryManager());
}
void RTCPCompoundPacket::ClearPacketList()
{
std::list<RTCPPacket *>::const_iterator it;
for (it = rtcppacklist.begin() ; it != rtcppacklist.end() ; it++)
RTPDelete(*it,GetMemoryManager());
rtcppacklist.clear();
rtcppackit = rtcppacklist.begin();
}
#ifdef RTPDEBUG
void RTCPCompoundPacket::Dump()
{
std::list<RTCPPacket *>::const_iterator it;
for (it = rtcppacklist.begin() ; it != rtcppacklist.end() ; it++)
{
RTCPPacket *p = *it;
p->Dump();
}
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,111 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpcompoundpacket.h
*/
#ifndef RTCPCOMPOUNDPACKET_H
#define RTCPCOMPOUNDPACKET_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
#include <list>
namespace jrtplib
{
class RTPRawPacket;
class RTCPPacket;
/** Represents an RTCP compound packet. */
class JRTPLIB_IMPORTEXPORT RTCPCompoundPacket : public RTPMemoryObject
{
public:
/** Creates an RTCPCompoundPacket instance from the data in \c rawpack, installing a memory manager if specified. */
RTCPCompoundPacket(RTPRawPacket &rawpack, RTPMemoryManager *memmgr = 0);
/** Creates an RTCPCompoundPacket instance from the data in \c packet}, with size \c len.
* Creates an RTCPCompoundPacket instance from the data in \c packet}, with size \c len. The \c deletedata
* flag specifies if the data in \c packet should be deleted when the compound packet is destroyed. If
* specified, a memory manager will be installed.
*/
RTCPCompoundPacket(uint8_t *packet, size_t len, bool deletedata = true, RTPMemoryManager *memmgr = 0);
protected:
RTCPCompoundPacket(RTPMemoryManager *memmgr); // this is for the compoundpacket builder
public:
virtual ~RTCPCompoundPacket();
/** Checks if the RTCP compound packet was created successfully.
* If the raw packet data in the constructor could not be parsed, this function returns the error code of
* what went wrong. If the packet had an invalid format, the return value is \c ERR_RTP_RTCPCOMPOUND_INVALIDPACKET.
*/
int GetCreationError() { return error; }
/** Returns a pointer to the data of the entire RTCP compound packet. */
const uint8_t *GetCompoundPacketData() { return compoundpacket; }
/** Returns the size of the entire RTCP compound packet. */
size_t GetCompoundPacketLength() { return compoundpacketlength; }
/** Starts the iteration over the individual RTCP packets in the RTCP compound packet. */
void GotoFirstPacket() { rtcppackit = rtcppacklist.begin(); }
/** Returns a pointer to the next individual RTCP packet.
* Returns a pointer to the next individual RTCP packet. Note that no \c delete call may be done
* on the RTCPPacket instance which is returned.
*/
RTCPPacket *GetNextPacket() { if (rtcppackit == rtcppacklist.end()) return 0; RTCPPacket *p = *rtcppackit; rtcppackit++; return p; }
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
protected:
void ClearPacketList();
int ParseData(uint8_t *packet, size_t len);
int error;
const uint8_t *compoundpacket;
size_t compoundpacketlength;
bool deletepacket;
std::list<RTCPPacket *> rtcppacklist;
std::list<RTCPPacket *>::const_iterator rtcppackit;
};
} // end namespace
#endif // RTCPCOMPOUNDPACKET_H

View File

@@ -0,0 +1,813 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpcompoundpacketbuilder.h"
#include "rtcpsrpacket.h"
#include "rtcprrpacket.h"
#include "rtcpsdespacket.h"
#include "rtcpbyepacket.h"
#include "rtcpapppacket.h"
#ifdef RTP_SUPPORT_RTCPUNKNOWN
#include "rtcpunknownpacket.h"
#endif // RTP_SUPPORT_RTCPUNKNOWN
#if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h>
#include <string.h>
#endif // WIN32
#include "rtpdebug.h"
namespace jrtplib
{
RTCPCompoundPacketBuilder::RTCPCompoundPacketBuilder(RTPMemoryManager *mgr) : RTCPCompoundPacket(mgr), report(mgr), sdes(mgr)
{
byesize = 0;
appsize = 0;
#ifdef RTP_SUPPORT_RTCPUNKNOWN
unknownsize = 0;
#endif // RTP_SUPPORT_RTCPUNKNOWN
maximumpacketsize = 0;
buffer = 0;
external = false;
arebuilding = false;
}
RTCPCompoundPacketBuilder::~RTCPCompoundPacketBuilder()
{
if (external)
compoundpacket = 0; // make sure RTCPCompoundPacket doesn't delete the external buffer
ClearBuildBuffers();
}
void RTCPCompoundPacketBuilder::ClearBuildBuffers()
{
report.Clear();
sdes.Clear();
std::list<Buffer>::const_iterator it;
for (it = byepackets.begin() ; it != byepackets.end() ; it++)
{
if ((*it).packetdata)
RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
}
for (it = apppackets.begin() ; it != apppackets.end() ; it++)
{
if ((*it).packetdata)
RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
}
#ifdef RTP_SUPPORT_RTCPUNKNOWN
for (it = unknownpackets.begin() ; it != unknownpackets.end() ; it++)
{
if ((*it).packetdata)
RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
}
#endif // RTP_SUPPORT_RTCPUNKNOWN
byepackets.clear();
apppackets.clear();
#ifdef RTP_SUPPORT_RTCPUNKNOWN
unknownpackets.clear();
#endif // RTP_SUPPORT_RTCPUNKNOWN
byesize = 0;
appsize = 0;
#ifdef RTP_SUPPORT_RTCPUNKNOWN
unknownsize = 0;
#endif // RTP_SUPPORT_RTCPUNKNOWN
}
int RTCPCompoundPacketBuilder::InitBuild(size_t maxpacketsize)
{
if (arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILDING;
if (compoundpacket)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILT;
if (maxpacketsize < RTP_MINPACKETSIZE)
return ERR_RTP_RTCPCOMPPACKBUILDER_MAXPACKETSIZETOOSMALL;
maximumpacketsize = maxpacketsize;
buffer = 0;
external = false;
byesize = 0;
appsize = 0;
#ifdef RTP_SUPPORT_RTCPUNKNOWN
unknownsize = 0;
#endif // RTP_SUPPORT_RTCPUNKNOWN
arebuilding = true;
return 0;
}
int RTCPCompoundPacketBuilder::InitBuild(void *externalbuffer,size_t buffersize)
{
if (arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILDING;
if (compoundpacket)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILT;
if (buffersize < RTP_MINPACKETSIZE)
return ERR_RTP_RTCPCOMPPACKBUILDER_BUFFERSIZETOOSMALL;
maximumpacketsize = buffersize;
buffer = (uint8_t *)externalbuffer;
external = true;
byesize = 0;
appsize = 0;
#ifdef RTP_SUPPORT_RTCPUNKNOWN
unknownsize = 0;
#endif // RTP_SUPPORT_RTCPUNKNOWN
arebuilding = true;
return 0;
}
int RTCPCompoundPacketBuilder::StartSenderReport(uint32_t senderssrc,const RTPNTPTime &ntptimestamp,uint32_t rtptimestamp,
uint32_t packetcount,uint32_t octetcount)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (report.headerlength != 0)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYGOTREPORT;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalsize = byesize+appsize+sdes.NeededBytes();
#else
size_t totalsize = byesize+appsize+unknownsize+sdes.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t sizeleft = maximumpacketsize-totalsize;
size_t neededsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t)+sizeof(RTCPSenderReport);
if (neededsize > sizeleft)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
// fill in some things
report.headerlength = sizeof(uint32_t)+sizeof(RTCPSenderReport);
report.isSR = true;
uint32_t *ssrc = (uint32_t *)report.headerdata;
*ssrc = htonl(senderssrc);
RTCPSenderReport *sr = (RTCPSenderReport *)(report.headerdata + sizeof(uint32_t));
sr->ntptime_msw = htonl(ntptimestamp.GetMSW());
sr->ntptime_lsw = htonl(ntptimestamp.GetLSW());
sr->rtptimestamp = htonl(rtptimestamp);
sr->packetcount = htonl(packetcount);
sr->octetcount = htonl(octetcount);
return 0;
}
int RTCPCompoundPacketBuilder::StartReceiverReport(uint32_t senderssrc)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (report.headerlength != 0)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYGOTREPORT;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalsize = byesize+appsize+sdes.NeededBytes();
#else
size_t totalsize = byesize+appsize+unknownsize+sdes.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t sizeleft = maximumpacketsize-totalsize;
size_t neededsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t);
if (neededsize > sizeleft)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
// fill in some things
report.headerlength = sizeof(uint32_t);
report.isSR = false;
uint32_t *ssrc = (uint32_t *)report.headerdata;
*ssrc = htonl(senderssrc);
return 0;
}
int RTCPCompoundPacketBuilder::AddReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t packetslost,uint32_t exthighestseq,
uint32_t jitter,uint32_t lsr,uint32_t dlsr)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (report.headerlength == 0)
return ERR_RTP_RTCPCOMPPACKBUILDER_REPORTNOTSTARTED;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalothersize = byesize+appsize+sdes.NeededBytes();
#else
size_t totalothersize = byesize+appsize+unknownsize+sdes.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t reportsizewithextrablock = report.NeededBytesWithExtraReportBlock();
if ((totalothersize+reportsizewithextrablock) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPRECEIVERREPORT) uint8_t[sizeof(RTCPReceiverReport)];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
RTCPReceiverReport *rr = (RTCPReceiverReport *)buf;
uint32_t *packlost = (uint32_t *)&packetslost;
uint32_t packlost2 = (*packlost);
rr->ssrc = htonl(ssrc);
rr->fractionlost = fractionlost;
rr->packetslost[2] = (uint8_t)(packlost2&0xFF);
rr->packetslost[1] = (uint8_t)((packlost2>>8)&0xFF);
rr->packetslost[0] = (uint8_t)((packlost2>>16)&0xFF);
rr->exthighseqnr = htonl(exthighestseq);
rr->jitter = htonl(jitter);
rr->lsr = htonl(lsr);
rr->dlsr = htonl(dlsr);
report.reportblocks.push_back(Buffer(buf,sizeof(RTCPReceiverReport)));
return 0;
}
int RTCPCompoundPacketBuilder::AddSDESSource(uint32_t ssrc)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalotherbytes = byesize+appsize+report.NeededBytes();
#else
size_t totalotherbytes = byesize+appsize+unknownsize+report.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t sdessizewithextrasource = sdes.NeededBytesWithExtraSource();
if ((totalotherbytes + sdessizewithextrasource) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
int status;
if ((status = sdes.AddSSRC(ssrc)) < 0)
return status;
return 0;
}
int RTCPCompoundPacketBuilder::AddSDESNormalItem(RTCPSDESPacket::ItemType t,const void *itemdata,uint8_t itemlength)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (sdes.sdessources.empty())
return ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE;
uint8_t itemid;
switch(t)
{
case RTCPSDESPacket::CNAME:
itemid = RTCP_SDES_ID_CNAME;
break;
case RTCPSDESPacket::NAME:
itemid = RTCP_SDES_ID_NAME;
break;
case RTCPSDESPacket::EMAIL:
itemid = RTCP_SDES_ID_EMAIL;
break;
case RTCPSDESPacket::PHONE:
itemid = RTCP_SDES_ID_PHONE;
break;
case RTCPSDESPacket::LOC:
itemid = RTCP_SDES_ID_LOCATION;
break;
case RTCPSDESPacket::TOOL:
itemid = RTCP_SDES_ID_TOOL;
break;
case RTCPSDESPacket::NOTE:
itemid = RTCP_SDES_ID_NOTE;
break;
default:
return ERR_RTP_RTCPCOMPPACKBUILDER_INVALIDITEMTYPE;
}
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalotherbytes = byesize+appsize+report.NeededBytes();
#else
size_t totalotherbytes = byesize+appsize+unknownsize+report.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t sdessizewithextraitem = sdes.NeededBytesWithExtraItem(itemlength);
if ((sdessizewithextraitem+totalotherbytes) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf;
size_t len;
buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPSDESBLOCK) uint8_t[sizeof(RTCPSDESHeader)+(size_t)itemlength];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
len = sizeof(RTCPSDESHeader)+(size_t)itemlength;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(buf);
sdeshdr->sdesid = itemid;
sdeshdr->length = itemlength;
if (itemlength != 0)
memcpy((buf + sizeof(RTCPSDESHeader)),itemdata,(size_t)itemlength);
sdes.AddItem(buf,len);
return 0;
}
#ifdef RTP_SUPPORT_SDESPRIV
int RTCPCompoundPacketBuilder::AddSDESPrivateItem(const void *prefixdata,uint8_t prefixlength,const void *valuedata,
uint8_t valuelength)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (sdes.sdessources.empty())
return ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE;
size_t itemlength = ((size_t)prefixlength)+1+((size_t)valuelength);
if (itemlength > 255)
return ERR_RTP_RTCPCOMPPACKBUILDER_TOTALITEMLENGTHTOOBIG;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalotherbytes = byesize+appsize+report.NeededBytes();
#else
size_t totalotherbytes = byesize+appsize+unknownsize+report.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t sdessizewithextraitem = sdes.NeededBytesWithExtraItem(itemlength);
if ((sdessizewithextraitem+totalotherbytes) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf;
size_t len;
buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPSDESBLOCK) uint8_t[sizeof(RTCPSDESHeader)+itemlength];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
len = sizeof(RTCPSDESHeader)+(size_t)itemlength;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(buf);
sdeshdr->sdesid = RTCP_SDES_ID_PRIVATE;
sdeshdr->length = itemlength;
buf[sizeof(RTCPSDESHeader)] = prefixlength;
if (prefixlength != 0)
memcpy((buf+sizeof(RTCPSDESHeader)+1),prefixdata,(size_t)prefixlength);
if (valuelength != 0)
memcpy((buf+sizeof(RTCPSDESHeader)+1+(size_t)prefixlength),valuedata,(size_t)valuelength);
sdes.AddItem(buf,len);
return 0;
}
#endif // RTP_SUPPORT_SDESPRIV
int RTCPCompoundPacketBuilder::AddBYEPacket(uint32_t *ssrcs,uint8_t numssrcs,const void *reasondata,uint8_t reasonlength)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (numssrcs > 31)
return ERR_RTP_RTCPCOMPPACKBUILDER_TOOMANYSSRCS;
size_t packsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t)*((size_t)numssrcs);
size_t zerobytes = 0;
if (reasonlength > 0)
{
packsize += 1; // 1 byte for the length;
packsize += (size_t)reasonlength;
size_t r = (packsize&0x03);
if (r != 0)
{
zerobytes = 4-r;
packsize += zerobytes;
}
}
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalotherbytes = appsize+byesize+sdes.NeededBytes()+report.NeededBytes();
#else
size_t totalotherbytes = appsize+unknownsize+byesize+sdes.NeededBytes()+report.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
if ((totalotherbytes + packsize) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf;
size_t numwords;
buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPBYEPACKET) uint8_t[packsize];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)buf;
hdr->version = 2;
hdr->padding = 0;
hdr->count = numssrcs;
numwords = packsize/sizeof(uint32_t);
hdr->length = htons((uint16_t)(numwords-1));
hdr->packettype = RTP_RTCPTYPE_BYE;
uint32_t *sources = (uint32_t *)(buf+sizeof(RTCPCommonHeader));
uint8_t srcindex;
for (srcindex = 0 ; srcindex < numssrcs ; srcindex++)
sources[srcindex] = htonl(ssrcs[srcindex]);
if (reasonlength != 0)
{
size_t offset = sizeof(RTCPCommonHeader)+((size_t)numssrcs)*sizeof(uint32_t);
buf[offset] = reasonlength;
memcpy((buf+offset+1),reasondata,(size_t)reasonlength);
for (size_t i = 0 ; i < zerobytes ; i++)
buf[packsize-1-i] = 0;
}
byepackets.push_back(Buffer(buf,packsize));
byesize += packsize;
return 0;
}
int RTCPCompoundPacketBuilder::AddAPPPacket(uint8_t subtype,uint32_t ssrc,const uint8_t name[4],const void *appdata,size_t appdatalen)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (subtype > 31)
return ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALSUBTYPE;
if ((appdatalen%4) != 0)
return ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALAPPDATALENGTH;
size_t appdatawords = appdatalen/4;
if ((appdatawords+2) > 65535)
return ERR_RTP_RTCPCOMPPACKBUILDER_APPDATALENTOOBIG;
size_t packsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t)*2+appdatalen;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalotherbytes = appsize+byesize+sdes.NeededBytes()+report.NeededBytes();
#else
size_t totalotherbytes = appsize+unknownsize+byesize+sdes.NeededBytes()+report.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
if ((totalotherbytes + packsize) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf;
buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPAPPPACKET) uint8_t[packsize];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)buf;
hdr->version = 2;
hdr->padding = 0;
hdr->count = subtype;
hdr->length = htons((uint16_t)(appdatawords+2));
hdr->packettype = RTP_RTCPTYPE_APP;
uint32_t *source = (uint32_t *)(buf+sizeof(RTCPCommonHeader));
*source = htonl(ssrc);
buf[sizeof(RTCPCommonHeader)+sizeof(uint32_t)+0] = name[0];
buf[sizeof(RTCPCommonHeader)+sizeof(uint32_t)+1] = name[1];
buf[sizeof(RTCPCommonHeader)+sizeof(uint32_t)+2] = name[2];
buf[sizeof(RTCPCommonHeader)+sizeof(uint32_t)+3] = name[3];
if (appdatalen > 0)
memcpy((buf+sizeof(RTCPCommonHeader)+sizeof(uint32_t)*2),appdata,appdatalen);
apppackets.push_back(Buffer(buf,packsize));
appsize += packsize;
return 0;
}
#ifdef RTP_SUPPORT_RTCPUNKNOWN
int RTCPCompoundPacketBuilder::AddUnknownPacket(uint8_t payload_type, uint8_t subtype, uint32_t ssrc, const void *data, size_t len)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
size_t datawords = len/4;
if ((datawords+2) > 65535)
return ERR_RTP_RTCPCOMPPACKBUILDER_APPDATALENTOOBIG;
size_t packsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t)+len;
size_t totalotherbytes = appsize+unknownsize+byesize+sdes.NeededBytes()+report.NeededBytes();
if ((totalotherbytes + packsize) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPUNKNOWNPACKET) uint8_t[packsize];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)buf;
hdr->version = 2;
hdr->padding = 0;
hdr->count = subtype;
hdr->length = htons((uint16_t)(datawords+1));
hdr->packettype = payload_type;
uint32_t *source = (uint32_t *)(buf+sizeof(RTCPCommonHeader));
*source = htonl(ssrc);
if (len > 0)
memcpy((buf+sizeof(RTCPCommonHeader)+sizeof(uint32_t)),data,len);
unknownpackets.push_back(Buffer(buf,packsize));
unknownsize += packsize;
return 0;
}
#endif // RTP_SUPPORT_RTCPUNKNOWN
int RTCPCompoundPacketBuilder::EndBuild()
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (report.headerlength == 0)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOREPORTPRESENT;
uint8_t *buf;
size_t len;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
len = appsize+byesize+report.NeededBytes()+sdes.NeededBytes();
#else
len = appsize+unknownsize+byesize+report.NeededBytes()+sdes.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
if (!external)
{
buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPCOMPOUNDPACKET) uint8_t[len];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
}
else
buf = buffer;
uint8_t *curbuf = buf;
RTCPPacket *p;
// first, we'll add all report info
{
bool firstpacket = true;
bool done = false;
std::list<Buffer>::const_iterator it = report.reportblocks.begin();
do
{
RTCPCommonHeader *hdr = (RTCPCommonHeader *)curbuf;
size_t offset;
hdr->version = 2;
hdr->padding = 0;
if (firstpacket && report.isSR)
{
hdr->packettype = RTP_RTCPTYPE_SR;
memcpy((curbuf+sizeof(RTCPCommonHeader)),report.headerdata,report.headerlength);
offset = sizeof(RTCPCommonHeader)+report.headerlength;
}
else
{
hdr->packettype = RTP_RTCPTYPE_RR;
memcpy((curbuf+sizeof(RTCPCommonHeader)),report.headerdata,sizeof(uint32_t));
offset = sizeof(RTCPCommonHeader)+sizeof(uint32_t);
}
firstpacket = false;
uint8_t count = 0;
while (it != report.reportblocks.end() && count < 31)
{
memcpy(curbuf+offset,(*it).packetdata,(*it).packetlength);
offset += (*it).packetlength;
count++;
it++;
}
size_t numwords = offset/sizeof(uint32_t);
hdr->length = htons((uint16_t)(numwords-1));
hdr->count = count;
// add entry in parent's list
if (hdr->packettype == RTP_RTCPTYPE_SR)
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPSRPACKET) RTCPSRPacket(curbuf,offset);
else
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPRRPACKET) RTCPRRPacket(curbuf,offset);
if (p == 0)
{
if (!external)
RTPDeleteByteArray(buf,GetMemoryManager());
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
curbuf += offset;
if (it == report.reportblocks.end())
done = true;
} while (!done);
}
// then, we'll add the sdes info
if (!sdes.sdessources.empty())
{
bool done = false;
std::list<SDESSource *>::const_iterator sourceit = sdes.sdessources.begin();
do
{
RTCPCommonHeader *hdr = (RTCPCommonHeader *)curbuf;
size_t offset = sizeof(RTCPCommonHeader);
hdr->version = 2;
hdr->padding = 0;
hdr->packettype = RTP_RTCPTYPE_SDES;
uint8_t sourcecount = 0;
while (sourceit != sdes.sdessources.end() && sourcecount < 31)
{
uint32_t *ssrc = (uint32_t *)(curbuf+offset);
*ssrc = htonl((*sourceit)->ssrc);
offset += sizeof(uint32_t);
std::list<Buffer>::const_iterator itemit,itemend;
itemit = (*sourceit)->items.begin();
itemend = (*sourceit)->items.end();
while (itemit != itemend)
{
memcpy(curbuf+offset,(*itemit).packetdata,(*itemit).packetlength);
offset += (*itemit).packetlength;
itemit++;
}
curbuf[offset] = 0; // end of item list;
offset++;
size_t r = offset&0x03;
if (r != 0) // align to 32 bit boundary
{
size_t num = 4-r;
size_t i;
for (i = 0 ; i < num ; i++)
curbuf[offset+i] = 0;
offset += num;
}
sourceit++;
sourcecount++;
}
size_t numwords = offset/4;
hdr->count = sourcecount;
hdr->length = htons((uint16_t)(numwords-1));
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPSDESPACKET) RTCPSDESPacket(curbuf,offset);
if (p == 0)
{
if (!external)
RTPDeleteByteArray(buf,GetMemoryManager());
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
curbuf += offset;
if (sourceit == sdes.sdessources.end())
done = true;
} while (!done);
}
// adding the app data
{
std::list<Buffer>::const_iterator it;
for (it = apppackets.begin() ; it != apppackets.end() ; it++)
{
memcpy(curbuf,(*it).packetdata,(*it).packetlength);
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPAPPPACKET) RTCPAPPPacket(curbuf,(*it).packetlength);
if (p == 0)
{
if (!external)
RTPDeleteByteArray(buf,GetMemoryManager());
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
curbuf += (*it).packetlength;
}
}
#ifdef RTP_SUPPORT_RTCPUNKNOWN
// adding the unknown data
{
std::list<Buffer>::const_iterator it;
for (it = unknownpackets.begin() ; it != unknownpackets.end() ; it++)
{
memcpy(curbuf,(*it).packetdata,(*it).packetlength);
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPUNKNOWNPACKET) RTCPUnknownPacket(curbuf,(*it).packetlength);
if (p == 0)
{
if (!external)
RTPDeleteByteArray(buf,GetMemoryManager());
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
curbuf += (*it).packetlength;
}
}
#endif // RTP_SUPPORT_RTCPUNKNOWN
// adding bye packets
{
std::list<Buffer>::const_iterator it;
for (it = byepackets.begin() ; it != byepackets.end() ; it++)
{
memcpy(curbuf,(*it).packetdata,(*it).packetlength);
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPBYEPACKET) RTCPBYEPacket(curbuf,(*it).packetlength);
if (p == 0)
{
if (!external)
RTPDeleteByteArray(buf,GetMemoryManager());
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
curbuf += (*it).packetlength;
}
}
compoundpacket = buf;
compoundpacketlength = len;
arebuilding = false;
ClearBuildBuffers();
return 0;
}
} // end namespace

View File

@@ -0,0 +1,400 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpcompoundpacketbuilder.h
*/
#ifndef RTCPCOMPOUNDPACKETBUILDER_H
#define RTCPCOMPOUNDPACKETBUILDER_H
#include "rtpconfig.h"
#include "rtcpcompoundpacket.h"
#include "rtptimeutilities.h"
#include "rtcpsdespacket.h"
#include "rtperrors.h"
#include <list>
namespace jrtplib
{
class RTPMemoryManager;
/** This class can be used to construct an RTCP compound packet.
* The RTCPCompoundPacketBuilder class can be used to construct an RTCP compound packet. It inherits the member
* functions of RTCPCompoundPacket which can be used to access the information in the compound packet once it has
* been built successfully. The member functions described below return \c ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT
* if the action would cause the maximum allowed size to be exceeded.
*/
class JRTPLIB_IMPORTEXPORT RTCPCompoundPacketBuilder : public RTCPCompoundPacket
{
public:
/** Constructs an RTCPCompoundPacketBuilder instance, optionally installing a memory manager. */
RTCPCompoundPacketBuilder(RTPMemoryManager *memmgr = 0);
~RTCPCompoundPacketBuilder();
/** Starts building an RTCP compound packet with maximum size \c maxpacketsize.
* Starts building an RTCP compound packet with maximum size \c maxpacketsize. New memory will be allocated
* to store the packet.
*/
int InitBuild(size_t maxpacketsize);
/** Starts building a RTCP compound packet.
* Starts building a RTCP compound packet. Data will be stored in \c externalbuffer which
* can contain \c buffersize bytes.
*/
int InitBuild(void *externalbuffer,size_t buffersize);
/** Adds a sender report to the compound packet.
* Tells the packet builder that the packet should start with a sender report which will contain
* the sender information specified by this function's arguments. Once the sender report is started,
* report blocks can be added using the AddReportBlock function.
*/
int StartSenderReport(uint32_t senderssrc,const RTPNTPTime &ntptimestamp,uint32_t rtptimestamp,
uint32_t packetcount,uint32_t octetcount);
/** Adds a receiver report to the compound packet.
* Tells the packet builder that the packet should start with a receiver report which will contain
* he sender SSRC \c senderssrc. Once the sender report is started, report blocks can be added using the
* AddReportBlock function.
*/
int StartReceiverReport(uint32_t senderssrc);
/** Adds the report block information specified by the function's arguments.
* Adds the report block information specified by the function's arguments. If more than 31 report blocks
* are added, the builder will automatically use a new RTCP receiver report packet.
*/
int AddReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t packetslost,uint32_t exthighestseq,
uint32_t jitter,uint32_t lsr,uint32_t dlsr);
/** Starts an SDES chunk for participant \c ssrc. */
int AddSDESSource(uint32_t ssrc);
/** Adds a normal (non-private) SDES item of type \c t to the current SDES chunk.
* Adds a normal (non-private) SDES item of type \c t to the current SDES chunk. The item's value
* will have length \c itemlength and will contain the data \c itemdata.
*/
int AddSDESNormalItem(RTCPSDESPacket::ItemType t,const void *itemdata,uint8_t itemlength);
#ifdef RTP_SUPPORT_SDESPRIV
/** Adds an SDES PRIV item described by the function's arguments to the current SDES chunk. */
int AddSDESPrivateItem(const void *prefixdata,uint8_t prefixlength,const void *valuedata,
uint8_t valuelength);
#endif // RTP_SUPPORT_SDESPRIV
/** Adds a BYE packet to the compound packet.
* Adds a BYE packet to the compound packet. It will contain \c numssrcs source identifiers specified in
* \c ssrcs and will indicate as reason for leaving the string of length \c reasonlength
* containing data \c reasondata.
*/
int AddBYEPacket(uint32_t *ssrcs,uint8_t numssrcs,const void *reasondata,uint8_t reasonlength);
/** Adds the APP packet specified by the arguments to the compound packet.
* Adds the APP packet specified by the arguments to the compound packet. Note that \c appdatalen has to be
* a multiple of four.
*/
int AddAPPPacket(uint8_t subtype,uint32_t ssrc,const uint8_t name[4],const void *appdata,size_t appdatalen);
/** Finishes building the compound packet.
* Finishes building the compound packet. If successful, the RTCPCompoundPacket member functions
* can be used to access the RTCP packet data.
*/
int EndBuild();
#ifdef RTP_SUPPORT_RTCPUNKNOWN
/** Adds the RTCP packet specified by the arguments to the compound packet.
* Adds the RTCP packet specified by the arguments to the compound packet.
*/
int AddUnknownPacket(uint8_t payload_type, uint8_t subtype, uint32_t ssrc, const void *data, size_t len);
#endif // RTP_SUPPORT_RTCPUNKNOWN
private:
class Buffer
{
public:
Buffer():packetdata(0),packetlength(0) { }
Buffer(uint8_t *data,size_t len):packetdata(data),packetlength(len) { }
uint8_t *packetdata;
size_t packetlength;
};
class Report : public RTPMemoryObject
{
public:
Report(RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
{
headerdata = (uint8_t *)headerdata32;
isSR = false;
headerlength = 0;
}
~Report() { Clear(); }
void Clear()
{
std::list<Buffer>::const_iterator it;
for (it = reportblocks.begin() ; it != reportblocks.end() ; it++)
{
if ((*it).packetdata)
RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
}
reportblocks.clear();
isSR = false;
headerlength = 0;
}
size_t NeededBytes()
{
size_t x,n,d,r;
n = reportblocks.size();
if (n == 0)
{
if (headerlength == 0)
return 0;
x = sizeof(RTCPCommonHeader)+headerlength;
}
else
{
x = n*sizeof(RTCPReceiverReport);
d = n/31; // max 31 reportblocks per report
r = n%31;
if (r != 0)
d++;
x += d*(sizeof(RTCPCommonHeader)+sizeof(uint32_t)); /* header and SSRC */
if (isSR)
x += sizeof(RTCPSenderReport);
}
return x;
}
size_t NeededBytesWithExtraReportBlock()
{
size_t x,n,d,r;
n = reportblocks.size() + 1; // +1 for the extra block
x = n*sizeof(RTCPReceiverReport);
d = n/31; // max 31 reportblocks per report
r = n%31;
if (r != 0)
d++;
x += d*(sizeof(RTCPCommonHeader)+sizeof(uint32_t)); /* header and SSRC */
if (isSR)
x += sizeof(RTCPSenderReport);
return x;
}
bool isSR;
uint8_t *headerdata;
uint32_t headerdata32[(sizeof(uint32_t)+sizeof(RTCPSenderReport))/sizeof(uint32_t)]; // either for ssrc and sender info or just ssrc
size_t headerlength;
std::list<Buffer> reportblocks;
};
class SDESSource : public RTPMemoryObject
{
public:
SDESSource(uint32_t s,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),ssrc(s),totalitemsize(0) { }
~SDESSource()
{
std::list<Buffer>::const_iterator it;
for (it = items.begin() ; it != items.end() ; it++)
{
if ((*it).packetdata)
RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
}
items.clear();
}
size_t NeededBytes()
{
size_t x,r;
x = totalitemsize + 1; // +1 for the 0 byte which terminates the item list
r = x%sizeof(uint32_t);
if (r != 0)
x += (sizeof(uint32_t)-r); // make sure it ends on a 32 bit boundary
x += sizeof(uint32_t); // for ssrc
return x;
}
size_t NeededBytesWithExtraItem(uint8_t itemdatalength)
{
size_t x,r;
x = totalitemsize + sizeof(RTCPSDESHeader) + (size_t)itemdatalength + 1;
r = x%sizeof(uint32_t);
if (r != 0)
x += (sizeof(uint32_t)-r); // make sure it ends on a 32 bit boundary
x += sizeof(uint32_t); // for ssrc
return x;
}
void AddItem(uint8_t *buf,size_t len)
{
Buffer b(buf,len);
totalitemsize += len;
items.push_back(b);
}
uint32_t ssrc;
std::list<Buffer> items;
private:
size_t totalitemsize;
};
class SDES : public RTPMemoryObject
{
public:
SDES(RTPMemoryManager *mgr) : RTPMemoryObject(mgr) { sdesit = sdessources.end(); }
~SDES() { Clear(); }
void Clear()
{
std::list<SDESSource *>::const_iterator it;
for (it = sdessources.begin() ; it != sdessources.end() ; it++)
RTPDelete(*it,GetMemoryManager());
sdessources.clear();
}
int AddSSRC(uint32_t ssrc)
{
SDESSource *s = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_SDESSOURCE) SDESSource(ssrc,GetMemoryManager());
if (s == 0)
return ERR_RTP_OUTOFMEM;
sdessources.push_back(s);
sdesit = sdessources.end();
sdesit--;
return 0;
}
int AddItem(uint8_t *buf,size_t len)
{
if (sdessources.empty())
return ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE;
(*sdesit)->AddItem(buf,len);
return 0;
}
size_t NeededBytes()
{
std::list<SDESSource *>::const_iterator it;
size_t x = 0;
size_t n,d,r;
if (sdessources.empty())
return 0;
for (it = sdessources.begin() ; it != sdessources.end() ; it++)
x += (*it)->NeededBytes();
n = sdessources.size();
d = n/31;
r = n%31;
if (r != 0)
d++;
x += d*sizeof(RTCPCommonHeader);
return x;
}
size_t NeededBytesWithExtraItem(uint8_t itemdatalength)
{
std::list<SDESSource *>::const_iterator it;
size_t x = 0;
size_t n,d,r;
if (sdessources.empty())
return 0;
for (it = sdessources.begin() ; it != sdesit ; it++)
x += (*it)->NeededBytes();
x += (*sdesit)->NeededBytesWithExtraItem(itemdatalength);
n = sdessources.size();
d = n/31;
r = n%31;
if (r != 0)
d++;
x += d*sizeof(RTCPCommonHeader);
return x;
}
size_t NeededBytesWithExtraSource()
{
std::list<SDESSource *>::const_iterator it;
size_t x = 0;
size_t n,d,r;
if (sdessources.empty())
return 0;
for (it = sdessources.begin() ; it != sdessources.end() ; it++)
x += (*it)->NeededBytes();
// for the extra source we'll need at least 8 bytes (ssrc and four 0 bytes)
x += sizeof(uint32_t)*2;
n = sdessources.size() + 1; // also, the number of sources will increase
d = n/31;
r = n%31;
if (r != 0)
d++;
x += d*sizeof(RTCPCommonHeader);
return x;
}
std::list<SDESSource *> sdessources;
private:
std::list<SDESSource *>::const_iterator sdesit;
};
size_t maximumpacketsize;
uint8_t *buffer;
bool external;
bool arebuilding;
Report report;
SDES sdes;
std::list<Buffer> byepackets;
size_t byesize;
std::list<Buffer> apppackets;
size_t appsize;
#ifdef RTP_SUPPORT_RTCPUNKNOWN
std::list<Buffer> unknownpackets;
size_t unknownsize;
#endif // RTP_SUPPORT_RTCPUNKNOWN
void ClearBuildBuffers();
};
} // end namespace
#endif // RTCPCOMPOUNDPACKETBUILDER_H

View File

@@ -0,0 +1,76 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcppacket.h"
#ifdef RTPDEBUG
#include <iostream>
#endif // RTPDEBUG
#include "rtpdebug.h"
#ifdef RTPDEBUG
namespace jrtplib
{
void RTCPPacket::Dump()
{
switch(packettype)
{
case SR:
std::cout << "RTCP Sender Report ";
break;
case RR:
std::cout << "RTCP Receiver Report ";
break;
case SDES:
std::cout << "RTCP Source Description ";
break;
case APP:
std::cout << "RTCP APP Packet ";
break;
case BYE:
std::cout << "RTCP Bye Packet ";
break;
case Unknown:
std::cout << "Unknown RTCP Packet ";
break;
default:
std::cout << "ERROR: Invalid packet type!" << std::endl;
}
std::cout << "Length: " << datalen;
std::cout << std::endl;
}
} // end namespace
#endif // RTPDEBUG

View File

@@ -0,0 +1,94 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcppacket.h
*/
#ifndef RTCPPACKET_H
#define RTCPPACKET_H
#include "rtpconfig.h"
#include "rtptypes.h"
namespace jrtplib
{
class RTCPCompoundPacket;
/** Base class for specific types of RTCP packets. */
class JRTPLIB_IMPORTEXPORT RTCPPacket
{
public:
/** Identifies the specific kind of RTCP packet. */
enum PacketType
{
SR, /**< An RTCP sender report. */
RR, /**< An RTCP receiver report. */
SDES, /**< An RTCP source description packet. */
BYE, /**< An RTCP bye packet. */
APP, /**< An RTCP packet containing application specific data. */
Unknown /**< The type of RTCP packet was not recognized. */
};
protected:
RTCPPacket(PacketType t,uint8_t *d,size_t dlen) : data(d),datalen(dlen),packettype(t) { knownformat = false; }
public:
virtual ~RTCPPacket() { }
/** Returns \c true if the subclass was able to interpret the data and \c false otherwise. */
bool IsKnownFormat() const { return knownformat; }
/** Returns the actual packet type which the subclass implements. */
PacketType GetPacketType() const { return packettype; }
/** Returns a pointer to the data of this RTCP packet. */
uint8_t *GetPacketData() { return data; }
/** Returns the length of this RTCP packet. */
size_t GetPacketLength() const { return datalen; }
#ifdef RTPDEBUG
virtual void Dump();
#endif // RTPDEBUG
protected:
uint8_t *data;
size_t datalen;
bool knownformat;
private:
const PacketType packettype;
};
} // end namespace
#endif // RTCPPACKET_H

View File

@@ -0,0 +1,741 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcppacketbuilder.h"
#include "rtpsources.h"
#include "rtppacketbuilder.h"
#include "rtcpscheduler.h"
#include "rtpsourcedata.h"
#include "rtcpcompoundpacketbuilder.h"
#include "rtpmemorymanager.h"
#include "rtpdebug.h"
namespace jrtplib
{
RTCPPacketBuilder::RTCPPacketBuilder(RTPSources &s,RTPPacketBuilder &pb,RTPMemoryManager *mgr)
: RTPMemoryObject(mgr),sources(s),rtppacketbuilder(pb),prevbuildtime(0,0),transmissiondelay(0,0),ownsdesinfo(mgr)
{
init = false;
#if (defined(WIN32) || defined(_WIN32_WCE))
timeinit.Dummy();
#endif // WIN32 || _WIN32_WCE
}
RTCPPacketBuilder::~RTCPPacketBuilder()
{
Destroy();
}
int RTCPPacketBuilder::Init(size_t maxpacksize,double tsunit,const void *cname,size_t cnamelen)
{
if (init)
return ERR_RTP_RTCPPACKETBUILDER_ALREADYINIT;
if (maxpacksize < RTP_MINPACKETSIZE)
return ERR_RTP_RTCPPACKETBUILDER_ILLEGALMAXPACKSIZE;
if (tsunit < 0.0)
return ERR_RTP_RTCPPACKETBUILDER_ILLEGALTIMESTAMPUNIT;
if (cnamelen>255)
cnamelen = 255;
maxpacketsize = maxpacksize;
timestampunit = tsunit;
int status;
if ((status = ownsdesinfo.SetCNAME((const uint8_t *)cname,cnamelen)) < 0)
return status;
ClearAllSourceFlags();
interval_name = -1;
interval_email = -1;
interval_location = -1;
interval_phone = -1;
interval_tool = -1;
interval_note = -1;
sdesbuildcount = 0;
transmissiondelay = RTPTime(0,0);
firstpacket = true;
processingsdes = false;
init = true;
return 0;
}
void RTCPPacketBuilder::Destroy()
{
if (!init)
return;
ownsdesinfo.Clear();
init = false;
}
int RTCPPacketBuilder::BuildNextPacket(RTCPCompoundPacket **pack)
{
if (!init)
return ERR_RTP_RTCPPACKETBUILDER_NOTINIT;
RTCPCompoundPacketBuilder *rtcpcomppack;
int status;
bool sender = false;
RTPSourceData *srcdat;
*pack = 0;
rtcpcomppack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPCOMPOUNDPACKETBUILDER) RTCPCompoundPacketBuilder(GetMemoryManager());
if (rtcpcomppack == 0)
return ERR_RTP_OUTOFMEM;
if ((status = rtcpcomppack->InitBuild(maxpacketsize)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
if ((srcdat = sources.GetOwnSourceInfo()) != 0)
{
if (srcdat->IsSender())
sender = true;
}
uint32_t ssrc = rtppacketbuilder.GetSSRC();
RTPTime curtime = RTPTime::CurrentTime();
if (sender)
{
RTPTime rtppacktime = rtppacketbuilder.GetPacketTime();
uint32_t rtppacktimestamp = rtppacketbuilder.GetPacketTimestamp();
uint32_t packcount = rtppacketbuilder.GetPacketCount();
uint32_t octetcount = rtppacketbuilder.GetPayloadOctetCount();
RTPTime diff = curtime;
diff -= rtppacktime;
diff += transmissiondelay; // the sample being sampled at this very instant will need a larger timestamp
uint32_t tsdiff = (uint32_t)((diff.GetDouble()/timestampunit)+0.5);
uint32_t rtptimestamp = rtppacktimestamp+tsdiff;
RTPNTPTime ntptimestamp = curtime.GetNTPTime();
if ((status = rtcpcomppack->StartSenderReport(ssrc,ntptimestamp,rtptimestamp,packcount,octetcount)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
}
else
{
if ((status = rtcpcomppack->StartReceiverReport(ssrc)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
}
uint8_t *owncname;
size_t owncnamelen;
owncname = ownsdesinfo.GetCNAME(&owncnamelen);
if ((status = rtcpcomppack->AddSDESSource(ssrc)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::CNAME,owncname,owncnamelen)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
if (!processingsdes)
{
int added,skipped;
bool full,atendoflist;
if ((status = FillInReportBlocks(rtcpcomppack,curtime,sources.GetTotalCount(),&full,&added,&skipped,&atendoflist)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
if (full && added == 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
}
if (!full)
{
processingsdes = true;
sdesbuildcount++;
ClearAllSourceFlags();
doname = false;
doemail = false;
doloc = false;
dophone = false;
dotool = false;
donote = false;
if (interval_name > 0 && ((sdesbuildcount%interval_name) == 0)) doname = true;
if (interval_email > 0 && ((sdesbuildcount%interval_email) == 0)) doemail = true;
if (interval_location > 0 && ((sdesbuildcount%interval_location) == 0)) doloc = true;
if (interval_phone > 0 && ((sdesbuildcount%interval_phone) == 0)) dophone = true;
if (interval_tool > 0 && ((sdesbuildcount%interval_tool) == 0)) dotool = true;
if (interval_note > 0 && ((sdesbuildcount%interval_note) == 0)) donote = true;
bool processedall;
int itemcount;
if ((status = FillInSDES(rtcpcomppack,&full,&processedall,&itemcount)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
if (processedall)
{
processingsdes = false;
ClearAllSDESFlags();
if (!full && skipped > 0)
{
// if the packet isn't full and we skipped some
// sources that we already got in a previous packet,
// we can add some of them now
bool atendoflist;
if ((status = FillInReportBlocks(rtcpcomppack,curtime,skipped,&full,&added,&skipped,&atendoflist)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
}
}
}
}
else // previous sdes processing wasn't finished
{
bool processedall;
int itemcount;
bool full;
if ((status = FillInSDES(rtcpcomppack,&full,&processedall,&itemcount)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
if (itemcount == 0) // Big problem: packet size is too small to let any progress happen
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
}
if (processedall)
{
processingsdes = false;
ClearAllSDESFlags();
if (!full)
{
// if the packet isn't full and we skipped some
// we can add some report blocks
int added,skipped;
bool atendoflist;
if ((status = FillInReportBlocks(rtcpcomppack,curtime,sources.GetTotalCount(),&full,&added,&skipped,&atendoflist)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
if (atendoflist) // filled in all possible sources
ClearAllSourceFlags();
}
}
}
if ((status = rtcpcomppack->EndBuild()) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
*pack = rtcpcomppack;
firstpacket = false;
prevbuildtime = curtime;
return 0;
}
void RTCPPacketBuilder::ClearAllSourceFlags()
{
if (sources.GotoFirstSource())
{
do
{
RTPSourceData *srcdat = sources.GetCurrentSourceInfo();
srcdat->SetProcessedInRTCP(false);
} while (sources.GotoNextSource());
}
}
int RTCPPacketBuilder::FillInReportBlocks(RTCPCompoundPacketBuilder *rtcpcomppack,const RTPTime &curtime,int maxcount,bool *full,int *added,int *skipped,bool *atendoflist)
{
RTPSourceData *srcdat;
int addedcount = 0;
int skippedcount = 0;
bool done = false;
bool filled = false;
bool atend = false;
int status;
if (sources.GotoFirstSource())
{
do
{
bool shouldprocess = false;
srcdat = sources.GetCurrentSourceInfo();
if (!srcdat->IsOwnSSRC()) // don't send to ourselves
{
if (!srcdat->IsCSRC()) // p 35: no reports should go to CSRCs
{
if (srcdat->INF_HasSentData()) // if this isn't true, INF_GetLastRTPPacketTime() won't make any sense
{
if (firstpacket)
shouldprocess = true;
else
{
// p 35: only if rtp packets were received since the last RTP packet, a report block
// should be added
RTPTime lastrtptime = srcdat->INF_GetLastRTPPacketTime();
if (lastrtptime > prevbuildtime)
shouldprocess = true;
}
}
}
}
if (shouldprocess)
{
if (srcdat->IsProcessedInRTCP()) // already covered this one
{
skippedcount++;
}
else
{
uint32_t rr_ssrc = srcdat->GetSSRC();
uint32_t num = srcdat->INF_GetNumPacketsReceivedInInterval();
uint32_t prevseq = srcdat->INF_GetSavedExtendedSequenceNumber();
uint32_t curseq = srcdat->INF_GetExtendedHighestSequenceNumber();
uint32_t expected = curseq-prevseq;
uint8_t fraclost;
if (expected < num) // got duplicates
fraclost = 0;
else
{
double lost = (double)(expected-num);
double frac = lost/((double)expected);
fraclost = (uint8_t)(frac*256.0);
}
expected = curseq-srcdat->INF_GetBaseSequenceNumber();
num = srcdat->INF_GetNumPacketsReceived();
uint32_t diff = expected-num;
int32_t *packlost = (int32_t *)&diff;
uint32_t jitter = srcdat->INF_GetJitter();
uint32_t lsr;
uint32_t dlsr;
if (!srcdat->SR_HasInfo())
{
lsr = 0;
dlsr = 0;
}
else
{
RTPNTPTime srtime = srcdat->SR_GetNTPTimestamp();
uint32_t m = (srtime.GetMSW()&0xFFFF);
uint32_t l = ((srtime.GetLSW()>>16)&0xFFFF);
lsr = ((m<<16)|l);
RTPTime diff = curtime;
diff -= srcdat->SR_GetReceiveTime();
double diff2 = diff.GetDouble();
diff2 *= 65536.0;
dlsr = (uint32_t)diff2;
}
status = rtcpcomppack->AddReportBlock(rr_ssrc,fraclost,*packlost,curseq,jitter,lsr,dlsr);
if (status < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
done = true;
filled = true;
}
else
return status;
}
else
{
addedcount++;
if (addedcount >= maxcount)
{
done = true;
if (!sources.GotoNextSource())
atend = true;
}
srcdat->INF_StartNewInterval();
srcdat->SetProcessedInRTCP(true);
}
}
}
if (!done)
{
if (!sources.GotoNextSource())
{
atend = true;
done = true;
}
}
} while (!done);
}
*added = addedcount;
*skipped = skippedcount;
*full = filled;
if (!atend) // search for available sources
{
bool shouldprocess = false;
do
{
srcdat = sources.GetCurrentSourceInfo();
if (!srcdat->IsOwnSSRC()) // don't send to ourselves
{
if (!srcdat->IsCSRC()) // p 35: no reports should go to CSRCs
{
if (srcdat->INF_HasSentData()) // if this isn't true, INF_GetLastRTPPacketTime() won't make any sense
{
if (firstpacket)
shouldprocess = true;
else
{
// p 35: only if rtp packets were received since the last RTP packet, a report block
// should be added
RTPTime lastrtptime = srcdat->INF_GetLastRTPPacketTime();
if (lastrtptime > prevbuildtime)
shouldprocess = true;
}
}
}
}
if (shouldprocess)
{
if (srcdat->IsProcessedInRTCP())
shouldprocess = false;
}
if (!shouldprocess)
{
if (!sources.GotoNextSource())
atend = true;
}
} while (!atend && !shouldprocess);
}
*atendoflist = atend;
return 0;
}
int RTCPPacketBuilder::FillInSDES(RTCPCompoundPacketBuilder *rtcpcomppack,bool *full,bool *processedall,int *added)
{
int status;
uint8_t *data;
size_t datalen;
*full = false;
*processedall = false;
*added = 0;
// We don't need to add a SSRC for our own data, this is still set
// from adding the CNAME
if (doname)
{
if (!ownsdesinfo.ProcessedName())
{
data = ownsdesinfo.GetName(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::NAME,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedName(true);
}
}
if (doemail)
{
if (!ownsdesinfo.ProcessedEMail())
{
data = ownsdesinfo.GetEMail(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::EMAIL,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedEMail(true);
}
}
if (doloc)
{
if (!ownsdesinfo.ProcessedLocation())
{
data = ownsdesinfo.GetLocation(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::LOC,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedLocation(true);
}
}
if (dophone)
{
if (!ownsdesinfo.ProcessedPhone())
{
data = ownsdesinfo.GetPhone(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::PHONE,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedPhone(true);
}
}
if (dotool)
{
if (!ownsdesinfo.ProcessedTool())
{
data = ownsdesinfo.GetTool(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::TOOL,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedTool(true);
}
}
if (donote)
{
if (!ownsdesinfo.ProcessedNote())
{
data = ownsdesinfo.GetNote(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::NOTE,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedNote(true);
}
}
*processedall = true;
return 0;
}
void RTCPPacketBuilder::ClearAllSDESFlags()
{
ownsdesinfo.ClearFlags();
}
int RTCPPacketBuilder::BuildBYEPacket(RTCPCompoundPacket **pack,const void *reason,size_t reasonlength,bool useSRifpossible)
{
if (!init)
return ERR_RTP_RTCPPACKETBUILDER_NOTINIT;
RTCPCompoundPacketBuilder *rtcpcomppack;
int status;
if (reasonlength > 255)
reasonlength = 255;
*pack = 0;
rtcpcomppack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPCOMPOUNDPACKETBUILDER) RTCPCompoundPacketBuilder(GetMemoryManager());
if (rtcpcomppack == 0)
return ERR_RTP_OUTOFMEM;
if ((status = rtcpcomppack->InitBuild(maxpacketsize)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
uint32_t ssrc = rtppacketbuilder.GetSSRC();
bool useSR = false;
if (useSRifpossible)
{
RTPSourceData *srcdat;
if ((srcdat = sources.GetOwnSourceInfo()) != 0)
{
if (srcdat->IsSender())
useSR = true;
}
}
if (useSR)
{
RTPTime curtime = RTPTime::CurrentTime();
RTPTime rtppacktime = rtppacketbuilder.GetPacketTime();
uint32_t rtppacktimestamp = rtppacketbuilder.GetPacketTimestamp();
uint32_t packcount = rtppacketbuilder.GetPacketCount();
uint32_t octetcount = rtppacketbuilder.GetPayloadOctetCount();
RTPTime diff = curtime;
diff -= rtppacktime;
uint32_t tsdiff = (uint32_t)((diff.GetDouble()/timestampunit)+0.5);
uint32_t rtptimestamp = rtppacktimestamp+tsdiff;
RTPNTPTime ntptimestamp = curtime.GetNTPTime();
if ((status = rtcpcomppack->StartSenderReport(ssrc,ntptimestamp,rtptimestamp,packcount,octetcount)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
}
else
{
if ((status = rtcpcomppack->StartReceiverReport(ssrc)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
}
uint8_t *owncname;
size_t owncnamelen;
owncname = ownsdesinfo.GetCNAME(&owncnamelen);
if ((status = rtcpcomppack->AddSDESSource(ssrc)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::CNAME,owncname,owncnamelen)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
uint32_t ssrcs[1];
ssrcs[0] = ssrc;
if ((status = rtcpcomppack->AddBYEPacket(ssrcs,1,(const uint8_t *)reason,reasonlength)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
if ((status = rtcpcomppack->EndBuild()) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
*pack = rtcpcomppack;
return 0;
}
} // end namespace

View File

@@ -0,0 +1,229 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcppacketbuilder.h
*/
#ifndef RTCPPACKETBUILDER_H
#define RTCPPACKETBUILDER_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtperrors.h"
#include "rtcpsdesinfo.h"
#include "rtptimeutilities.h"
#include "rtpmemoryobject.h"
namespace jrtplib
{
class RTPSources;
class RTPPacketBuilder;
class RTCPScheduler;
class RTCPCompoundPacket;
class RTCPCompoundPacketBuilder;
/** This class can be used to build RTCP compound packets, on a higher level than the RTCPCompoundPacketBuilder.
* The class RTCPPacketBuilder can be used to build RTCP compound packets. This class is more high-level
* than the RTCPCompoundPacketBuilder class: it uses the information of an RTPPacketBuilder instance and of
* an RTPSources instance to automatically generate the next compound packet which should be sent. It also
* provides functions to determine when SDES items other than the CNAME item should be sent.
*/
class JRTPLIB_IMPORTEXPORT RTCPPacketBuilder : public RTPMemoryObject
{
public:
/** Creates an RTCPPacketBuilder instance.
* Creates an instance which will use the source table \c sources and the RTP packet builder
* \c rtppackbuilder to determine the information for the next RTCP compound packet. Optionally,
* the memory manager \c mgr can be installed.
*/
RTCPPacketBuilder(RTPSources &sources,RTPPacketBuilder &rtppackbuilder, RTPMemoryManager *mgr = 0);
~RTCPPacketBuilder();
/** Initializes the builder.
* Initializes the builder to use the maximum allowed packet size \c maxpacksize, timestamp unit
* \c timestampunit and the SDES CNAME item specified by \c cname with length \c cnamelen.
* The timestamp unit is defined as a time interval divided by the timestamp interval corresponding to
* that interval: for 8000 Hz audio this would be 1/8000.
*/
int Init(size_t maxpacksize,double timestampunit,const void *cname,size_t cnamelen);
/** Cleans up the builder. */
void Destroy();
/** Sets the timestamp unit to be used to \c tsunit.
* Sets the timestamp unit to be used to \c tsunit. The timestamp unit is defined as a time interval
* divided by the timestamp interval corresponding to that interval: for 8000 Hz audio this would
* be 1/8000.
*/
int SetTimestampUnit(double tsunit) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; if (tsunit < 0) return ERR_RTP_RTCPPACKETBUILDER_ILLEGALTIMESTAMPUNIT; timestampunit = tsunit; return 0; }
/** Sets the maximum size allowed size of an RTCP compound packet to \c maxpacksize. */
int SetMaximumPacketSize(size_t maxpacksize) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; if (maxpacksize < RTP_MINPACKETSIZE) return ERR_RTP_RTCPPACKETBUILDER_ILLEGALMAXPACKSIZE; maxpacketsize = maxpacksize; return 0; }
/** This function allows you to inform RTCP packet builder about the delay between sampling the first
* sample of a packet and sending the packet.
* This function allows you to inform RTCP packet builder about the delay between sampling the first
* sample of a packet and sending the packet. This delay is taken into account when calculating the
* relation between RTP timestamp and wallclock time, used for inter-media synchronization.
*/
int SetPreTransmissionDelay(const RTPTime &delay) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; transmissiondelay = delay; return 0; }
/** Builds the next RTCP compound packet which should be sent and stores it in \c pack. */
int BuildNextPacket(RTCPCompoundPacket **pack);
/** Builds a BYE packet with reason for leaving specified by \c reason and length \c reasonlength.
* Builds a BYE packet with reason for leaving specified by \c reason and length \c reasonlength. If
* \c useSRifpossible is set to \c true, the RTCP compound packet will start with a sender report if
* allowed. Otherwise, a receiver report is used.
*/
int BuildBYEPacket(RTCPCompoundPacket **pack,const void *reason,size_t reasonlength,bool useSRifpossible = true);
/** Sets the RTCP interval for the SDES name item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES name item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetNameInterval(int count) { if (!init) return; interval_name = count; }
/** Sets the RTCP interval for the SDES e-mail item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES e-mail item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetEMailInterval(int count) { if (!init) return; interval_email = count; }
/** Sets the RTCP interval for the SDES location item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES location item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetLocationInterval(int count) { if (!init) return; interval_location = count; }
/** Sets the RTCP interval for the SDES phone item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES phone item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetPhoneInterval(int count) { if (!init) return; interval_phone = count; }
/** Sets the RTCP interval for the SDES tool item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES tool item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetToolInterval(int count) { if (!init) return; interval_tool = count; }
/** Sets the RTCP interval for the SDES note item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES note item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetNoteInterval(int count) { if (!init) return; interval_note = count; }
/** Sets the SDES name item for the local participant to the value \c s with length \c len. */
int SetLocalName(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetName((const uint8_t *)s,len); }
/** Sets the SDES e-mail item for the local participant to the value \c s with length \c len. */
int SetLocalEMail(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetEMail((const uint8_t *)s,len); }
/** Sets the SDES location item for the local participant to the value \c s with length \c len. */
int SetLocalLocation(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetLocation((const uint8_t *)s,len); }
/** Sets the SDES phone item for the local participant to the value \c s with length \c len. */
int SetLocalPhone(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetPhone((const uint8_t *)s,len); }
/** Sets the SDES tool item for the local participant to the value \c s with length \c len. */
int SetLocalTool(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetTool((const uint8_t *)s,len); }
/** Sets the SDES note item for the local participant to the value \c s with length \c len. */
int SetLocalNote(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetNote((const uint8_t *)s,len); }
/** Returns the own CNAME item with length \c len */
uint8_t *GetLocalCNAME(size_t *len) const { if (!init) return 0; return ownsdesinfo.GetCNAME(len); }
private:
void ClearAllSourceFlags();
int FillInReportBlocks(RTCPCompoundPacketBuilder *pack,const RTPTime &curtime,int maxcount,bool *full,int *added,int *skipped,bool *atendoflist);
int FillInSDES(RTCPCompoundPacketBuilder *pack,bool *full,bool *processedall,int *added);
void ClearAllSDESFlags();
RTPSources &sources;
RTPPacketBuilder &rtppacketbuilder;
bool init;
size_t maxpacketsize;
double timestampunit;
bool firstpacket;
RTPTime prevbuildtime,transmissiondelay;
class RTCPSDESInfoInternal : public RTCPSDESInfo
{
public:
RTCPSDESInfoInternal(RTPMemoryManager *mgr) : RTCPSDESInfo(mgr) { ClearFlags(); }
void ClearFlags() { pname = false; pemail = false; plocation = false; pphone = false; ptool = false; pnote = false; }
bool ProcessedName() const { return pname; }
bool ProcessedEMail() const { return pemail; }
bool ProcessedLocation() const { return plocation; }
bool ProcessedPhone() const { return pphone; }
bool ProcessedTool() const { return ptool; }
bool ProcessedNote() const { return pnote; }
void SetProcessedName(bool v) { pname = v; }
void SetProcessedEMail(bool v) { pemail = v; }
void SetProcessedLocation(bool v) { plocation = v; }
void SetProcessedPhone(bool v) { pphone = v; }
void SetProcessedTool(bool v) { ptool = v; }
void SetProcessedNote(bool v) { pnote = v; }
private:
bool pname,pemail,plocation,pphone,ptool,pnote;
};
RTCPSDESInfoInternal ownsdesinfo;
int interval_name,interval_email,interval_location;
int interval_phone,interval_tool,interval_note;
bool doname,doemail,doloc,dophone,dotool,donote;
bool processingsdes;
int sdesbuildcount;
};
} // end namespace
#endif // RTCPPACKETBUILDER_H

View File

@@ -0,0 +1,100 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcprrpacket.h"
#ifdef RTPDEBUG
#include <iostream>
#endif // RTPDEBUG
#include "rtpdebug.h"
namespace jrtplib
{
RTCPRRPacket::RTCPRRPacket(uint8_t *data,size_t datalength)
: RTCPPacket(RR,data,datalength)
{
knownformat = false;
RTCPCommonHeader *hdr;
size_t len = datalength;
size_t expectedlength;
hdr = (RTCPCommonHeader *)data;
if (hdr->padding)
{
uint8_t padcount = data[datalength-1];
if ((padcount & 0x03) != 0) // not a multiple of four! (see rfc 3550 p 37)
return;
if (((size_t)padcount) >= len)
return;
len -= (size_t)padcount;
}
expectedlength = sizeof(RTCPCommonHeader)+sizeof(uint32_t);
expectedlength += sizeof(RTCPReceiverReport)*((int)hdr->count);
if (expectedlength != len)
return;
knownformat = true;
}
#ifdef RTPDEBUG
void RTCPRRPacket::Dump()
{
RTCPPacket::Dump();
if (!IsKnownFormat())
std::cout << " Unknown format" << std::endl;
else
{
int num = GetReceptionReportCount();
int i;
std::cout << " SSRC of sender: " << GetSenderSSRC() << std::endl;
for (i = 0 ; i < num ; i++)
{
std::cout << " Report block " << i << std::endl;
std::cout << " SSRC: " << GetSSRC(i) << std::endl;
std::cout << " Fraction lost: " << (uint32_t)GetFractionLost(i) << std::endl;
std::cout << " Packets lost: " << GetLostPacketCount(i) << std::endl;
std::cout << " Seq. nr.: " << GetExtendedHighestSequenceNumber(i) << std::endl;
std::cout << " Jitter: " << GetJitter(i) << std::endl;
std::cout << " LSR: " << GetLSR(i) << std::endl;
std::cout << " DLSR: " << GetDLSR(i) << std::endl;
}
}
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,206 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcprrpacket.h
*/
#ifndef RTCPRRPACKET_H
#define RTCPRRPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
#include "rtpstructs.h"
#if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h>
#endif // WIN32
namespace jrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP receiver report packet. */
class JRTPLIB_IMPORTEXPORT RTCPRRPacket : public RTCPPacket
{
public:
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it points
* to is valid as long as the class instance exists.
*/
RTCPRRPacket(uint8_t *data,size_t datalen);
~RTCPRRPacket() { }
/** Returns the SSRC of the participant who sent this packet. */
uint32_t GetSenderSSRC() const;
/** Returns the number of reception report blocks present in this packet. */
int GetReceptionReportCount() const;
/** Returns the SSRC of the reception report block described by \c index which may have a value
* from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetSSRC(int index) const;
/** Returns the `fraction lost' field of the reception report described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint8_t GetFractionLost(int index) const;
/** Returns the number of lost packets in the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
int32_t GetLostPacketCount(int index) const;
/** Returns the extended highest sequence number of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetExtendedHighestSequenceNumber(int index) const;
/** Returns the jitter field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetJitter(int index) const;
/** Returns the LSR field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetLSR(int index) const;
/** Returns the DLSR field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetDLSR(int index) const;
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
private:
RTCPReceiverReport *GotoReport(int index) const;
};
inline uint32_t RTCPRRPacket::GetSenderSSRC() const
{
if (!knownformat)
return 0;
uint32_t *ssrcptr = (uint32_t *)(data+sizeof(RTCPCommonHeader));
return ntohl(*ssrcptr);
}
inline int RTCPRRPacket::GetReceptionReportCount() const
{
if (!knownformat)
return 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
return ((int)hdr->count);
}
inline RTCPReceiverReport *RTCPRRPacket::GotoReport(int index) const
{
RTCPReceiverReport *r = (RTCPReceiverReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t)+index*sizeof(RTCPReceiverReport));
return r;
}
inline uint32_t RTCPRRPacket::GetSSRC(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->ssrc);
}
inline uint8_t RTCPRRPacket::GetFractionLost(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return r->fractionlost;
}
inline int32_t RTCPRRPacket::GetLostPacketCount(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
uint32_t count = ((uint32_t)r->packetslost[2])|(((uint32_t)r->packetslost[1])<<8)|(((uint32_t)r->packetslost[0])<<16);
if ((count&0x00800000) != 0) // test for negative number
count |= 0xFF000000;
int32_t *count2 = (int32_t *)(&count);
return (*count2);
}
inline uint32_t RTCPRRPacket::GetExtendedHighestSequenceNumber(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->exthighseqnr);
}
inline uint32_t RTCPRRPacket::GetJitter(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->jitter);
}
inline uint32_t RTCPRRPacket::GetLSR(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->lsr);
}
inline uint32_t RTCPRRPacket::GetDLSR(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->dlsr);
}
} // end namespace
#endif // RTCPRRPACKET_H

View File

@@ -0,0 +1,423 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpscheduler.h"
#include "rtpsources.h"
#include "rtpdefines.h"
#include "rtcppacket.h"
#include "rtppacket.h"
#include "rtcpcompoundpacket.h"
#include "rtpsourcedata.h"
#include "rtpdebug.h"
#define RTCPSCHED_MININTERVAL 1.0
namespace jrtplib
{
RTCPSchedulerParams::RTCPSchedulerParams() : mininterval(RTCP_DEFAULTMININTERVAL)
{
bandwidth = 1000; // TODO What is a good value here?
senderfraction = RTCP_DEFAULTSENDERFRACTION;
usehalfatstartup = RTCP_DEFAULTHALFATSTARTUP;
immediatebye = RTCP_DEFAULTIMMEDIATEBYE;
#if (defined(WIN32) || defined(_WIN32_WCE))
timeinit.Dummy();
#endif // WIN32 || _WIN32_WCE
}
RTCPSchedulerParams::~RTCPSchedulerParams()
{
}
int RTCPSchedulerParams::SetRTCPBandwidth(double bw)
{
if (bw < 0.0)
return ERR_RTP_SCHEDPARAMS_INVALIDBANDWIDTH;
bandwidth = bw;
return 0;
}
int RTCPSchedulerParams::SetSenderBandwidthFraction(double fraction)
{
if (fraction < 0.0 || fraction > 1.0)
return ERR_RTP_SCHEDPARAMS_BADFRACTION;
senderfraction = fraction;
return 0;
}
int RTCPSchedulerParams::SetMinimumTransmissionInterval(const RTPTime &t)
{
double t2 = t.GetDouble();
if (t2 < RTCPSCHED_MININTERVAL)
return ERR_RTP_SCHEDPARAMS_BADMINIMUMINTERVAL;
mininterval = t;
return 0;
}
RTCPScheduler::RTCPScheduler(RTPSources &s, RTPRandom &r) : rtprand(r),sources(s),nextrtcptime(0,0),prevrtcptime(0,0)
{
Reset();
//std::cout << (void *)(&rtprand) << std::endl;
}
RTCPScheduler::~RTCPScheduler()
{
}
void RTCPScheduler::Reset()
{
headeroverhead = 0; // user has to set this to an appropriate value
hassentrtcp = false;
firstcall = true;
avgrtcppacksize = 1000; // TODO: what is a good value for this?
byescheduled = false;
sendbyenow = false;
}
void RTCPScheduler::AnalyseIncoming(RTCPCompoundPacket &rtcpcomppack)
{
bool isbye = false;
RTCPPacket *p;
rtcpcomppack.GotoFirstPacket();
while (!isbye && ((p = rtcpcomppack.GetNextPacket()) != 0))
{
if (p->GetPacketType() == RTCPPacket::BYE)
isbye = true;
}
if (!isbye)
{
size_t packsize = headeroverhead+rtcpcomppack.GetCompoundPacketLength();
avgrtcppacksize = (size_t)((1.0/16.0)*((double)packsize)+(15.0/16.0)*((double)avgrtcppacksize));
}
else
{
if (byescheduled)
{
size_t packsize = headeroverhead+rtcpcomppack.GetCompoundPacketLength();
avgbyepacketsize = (size_t)((1.0/16.0)*((double)packsize)+(15.0/16.0)*((double)avgbyepacketsize));
byemembers++;
}
}
}
void RTCPScheduler::AnalyseOutgoing(RTCPCompoundPacket &rtcpcomppack)
{
bool isbye = false;
RTCPPacket *p;
rtcpcomppack.GotoFirstPacket();
while (!isbye && ((p = rtcpcomppack.GetNextPacket()) != 0))
{
if (p->GetPacketType() == RTCPPacket::BYE)
isbye = true;
}
if (!isbye)
{
size_t packsize = headeroverhead+rtcpcomppack.GetCompoundPacketLength();
avgrtcppacksize = (size_t)((1.0/16.0)*((double)packsize)+(15.0/16.0)*((double)avgrtcppacksize));
}
hassentrtcp = true;
}
RTPTime RTCPScheduler::GetTransmissionDelay()
{
if (firstcall)
{
firstcall = false;
prevrtcptime = RTPTime::CurrentTime();
pmembers = sources.GetActiveMemberCount();
CalculateNextRTCPTime();
}
RTPTime curtime = RTPTime::CurrentTime();
if (curtime > nextrtcptime) // packet should be sent
return RTPTime(0,0);
RTPTime diff = nextrtcptime;
diff -= curtime;
return diff;
}
bool RTCPScheduler::IsTime()
{
if (firstcall)
{
firstcall = false;
prevrtcptime = RTPTime::CurrentTime();
pmembers = sources.GetActiveMemberCount();
CalculateNextRTCPTime();
return false;
}
RTPTime currenttime = RTPTime::CurrentTime();
// // TODO: for debugging
// double diff = nextrtcptime.GetDouble() - currenttime.GetDouble();
//
// std::cout << "Delay till next RTCP interval: " << diff << std::endl;
if (currenttime < nextrtcptime) // timer has not yet expired
return false;
RTPTime checktime(0,0);
if (!byescheduled)
{
bool aresender = false;
RTPSourceData *srcdat;
if ((srcdat = sources.GetOwnSourceInfo()) != 0)
aresender = srcdat->IsSender();
checktime = CalculateTransmissionInterval(aresender);
}
else
checktime = CalculateBYETransmissionInterval();
// std::cout << "Calculated checktime: " << checktime.GetDouble() << std::endl;
checktime += prevrtcptime;
if (checktime <= currenttime) // Okay
{
byescheduled = false;
prevrtcptime = currenttime;
pmembers = sources.GetActiveMemberCount();
CalculateNextRTCPTime();
return true;
}
// std::cout << "New delay: " << nextrtcptime.GetDouble() - currenttime.GetDouble() << std::endl;
nextrtcptime = checktime;
pmembers = sources.GetActiveMemberCount();
return false;
}
void RTCPScheduler::CalculateNextRTCPTime()
{
bool aresender = false;
RTPSourceData *srcdat;
if ((srcdat = sources.GetOwnSourceInfo()) != 0)
aresender = srcdat->IsSender();
nextrtcptime = RTPTime::CurrentTime();
nextrtcptime += CalculateTransmissionInterval(aresender);
}
RTPTime RTCPScheduler::CalculateDeterministicInterval(bool sender /* = false */)
{
int numsenders = sources.GetSenderCount();
int numtotal = sources.GetActiveMemberCount();
// std::cout << "CalculateDeterministicInterval" << std::endl;
// std::cout << " numsenders: " << numsenders << std::endl;
// std::cout << " numtotal: " << numtotal << std::endl;
// Try to avoid division by zero:
if (numtotal == 0)
numtotal++;
double sfraction = ((double)numsenders)/((double)numtotal);
double C,n;
if (sfraction <= schedparams.GetSenderBandwidthFraction())
{
if (sender)
{
C = ((double)avgrtcppacksize)/(schedparams.GetSenderBandwidthFraction()*schedparams.GetRTCPBandwidth());
n = (double)numsenders;
}
else
{
C = ((double)avgrtcppacksize)/((1.0-schedparams.GetSenderBandwidthFraction())*schedparams.GetRTCPBandwidth());
n = (double)(numtotal-numsenders);
}
}
else
{
C = ((double)avgrtcppacksize)/schedparams.GetRTCPBandwidth();
n = (double)numtotal;
}
RTPTime Tmin = schedparams.GetMinimumTransmissionInterval();
double tmin = Tmin.GetDouble();
if (!hassentrtcp && schedparams.GetUseHalfAtStartup())
tmin /= 2.0;
double ntimesC = n*C;
double Td = (tmin>ntimesC)?tmin:ntimesC;
// TODO: for debugging
// std::cout << " Td: " << Td << std::endl;
return RTPTime(Td);
}
RTPTime RTCPScheduler::CalculateTransmissionInterval(bool sender)
{
RTPTime Td = CalculateDeterministicInterval(sender);
double td,mul,T;
// std::cout << "CalculateTransmissionInterval" << std::endl;
td = Td.GetDouble();
mul = rtprand.GetRandomDouble()+0.5; // gives random value between 0.5 and 1.5
T = (td*mul)/1.21828; // see RFC 3550 p 30
// std::cout << " Td: " << td << std::endl;
// std::cout << " mul: " << mul << std::endl;
// std::cout << " T: " << T << std::endl;
return RTPTime(T);
}
void RTCPScheduler::PerformReverseReconsideration()
{
if (firstcall)
return;
double diff1,diff2;
int members = sources.GetActiveMemberCount();
RTPTime tc = RTPTime::CurrentTime();
RTPTime tn_min_tc = nextrtcptime;
if (tn_min_tc > tc)
tn_min_tc -= tc;
else
tn_min_tc = RTPTime(0,0);
// std::cout << "+tn_min_tc0 " << nextrtcptime.GetDouble()-tc.GetDouble() << std::endl;
// std::cout << "-tn_min_tc0 " << -nextrtcptime.GetDouble()+tc.GetDouble() << std::endl;
// std::cout << "tn_min_tc " << tn_min_tc.GetDouble() << std::endl;
RTPTime tc_min_tp = tc;
if (tc_min_tp > prevrtcptime)
tc_min_tp -= prevrtcptime;
else
tc_min_tp = 0;
if (pmembers == 0) // avoid division by zero
pmembers++;
diff1 = (((double)members)/((double)pmembers))*tn_min_tc.GetDouble();
diff2 = (((double)members)/((double)pmembers))*tc_min_tp.GetDouble();
nextrtcptime = tc;
prevrtcptime = tc;
nextrtcptime += RTPTime(diff1);
prevrtcptime -= RTPTime(diff2);
pmembers = members;
}
void RTCPScheduler::ScheduleBYEPacket(size_t packetsize)
{
if (byescheduled)
return;
if (firstcall)
{
firstcall = false;
pmembers = sources.GetActiveMemberCount();
}
byescheduled = true;
avgbyepacketsize = packetsize+headeroverhead;
// For now, we will always use the BYE backoff algorithm as described in rfc 3550 p 33
byemembers = 1;
pbyemembers = 1;
if (schedparams.GetRequestImmediateBYE() && sources.GetActiveMemberCount() < 50) // p 34 (top)
sendbyenow = true;
else
sendbyenow = false;
prevrtcptime = RTPTime::CurrentTime();
nextrtcptime = prevrtcptime;
nextrtcptime += CalculateBYETransmissionInterval();
}
void RTCPScheduler::ActiveMemberDecrease()
{
if (sources.GetActiveMemberCount() < pmembers)
PerformReverseReconsideration();
}
RTPTime RTCPScheduler::CalculateBYETransmissionInterval()
{
if (!byescheduled)
return RTPTime(0,0);
if (sendbyenow)
return RTPTime(0,0);
double C,n;
C = ((double)avgbyepacketsize)/((1.0-schedparams.GetSenderBandwidthFraction())*schedparams.GetRTCPBandwidth());
n = (double)byemembers;
RTPTime Tmin = schedparams.GetMinimumTransmissionInterval();
double tmin = Tmin.GetDouble();
if (schedparams.GetUseHalfAtStartup())
tmin /= 2.0;
double ntimesC = n*C;
double Td = (tmin>ntimesC)?tmin:ntimesC;
double mul = rtprand.GetRandomDouble()+0.5; // gives random value between 0.5 and 1.5
double T = (Td*mul)/1.21828; // see RFC 3550 p 30
return RTPTime(T);
}
} // end namespace

View File

@@ -0,0 +1,189 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpscheduler.h
*/
#ifndef RTCPSCHEDULER_H
#define RTCPSCHEDULER_H
#include "rtpconfig.h"
#include "rtptimeutilities.h"
#include "rtprandom.h"
namespace jrtplib
{
class RTCPCompoundPacket;
class RTPPacket;
class RTPSources;
/** Describes parameters used by the RTCPScheduler class. */
class JRTPLIB_IMPORTEXPORT RTCPSchedulerParams
{
public:
RTCPSchedulerParams();
~RTCPSchedulerParams();
/** Sets the RTCP bandwidth to be used to \c bw (in bytes per second). */
int SetRTCPBandwidth(double bw);
/** Returns the used RTCP bandwidth in bytes per second (default is 1000). */
double GetRTCPBandwidth() const { return bandwidth; }
/** Sets the fraction of the RTCP bandwidth reserved for senders to \c fraction. */
int SetSenderBandwidthFraction(double fraction);
/** Returns the fraction of the RTCP bandwidth reserved for senders (default is 25%). */
double GetSenderBandwidthFraction() const { return senderfraction; }
/** Sets the minimum (deterministic) interval between RTCP compound packets to \c t. */
int SetMinimumTransmissionInterval(const RTPTime &t);
/** Returns the minimum RTCP transmission interval (default is 5 seconds). */
RTPTime GetMinimumTransmissionInterval() const { return mininterval; }
/** If \c usehalf is \c true, only use half the minimum interval before sending the first RTCP compound packet. */
void SetUseHalfAtStartup(bool usehalf) { usehalfatstartup = usehalf; }
/** Returns \c true if only half the minimum interval should be used before sending the first RTCP compound packet
* (defualt is \c true).
*/
bool GetUseHalfAtStartup() const { return usehalfatstartup; }
/** If \c v is \c true, the scheduler will schedule a BYE packet to be sent immediately if allowed. */
void SetRequestImmediateBYE(bool v) { immediatebye = v; }
/** Returns if the scheduler will schedule a BYE packet to be sent immediately if allowed
* (default is \c true).
*/
bool GetRequestImmediateBYE() const { return immediatebye; }
private:
double bandwidth;
double senderfraction;
RTPTime mininterval;
bool usehalfatstartup;
bool immediatebye;
};
/** This class determines when RTCP compound packets should be sent. */
class JRTPLIB_IMPORTEXPORT RTCPScheduler
{
public:
/** Creates an instance which will use the source table RTPSources to determine when RTCP compound
* packets should be scheduled.
* Creates an instance which will use the source table RTPSources to determine when RTCP compound
* packets should be scheduled. Note that for correct operation the \c sources instance should have information
* about the own SSRC (added by RTPSources::CreateOwnSSRC). You must also supply a random number
* generator \c rtprand which will be used for adding randomness to the RTCP intervals.
*/
RTCPScheduler(RTPSources &sources, RTPRandom &rtprand);
~RTCPScheduler();
/** Resets the scheduler. */
void Reset();
/** Sets the scheduler parameters to be used to \c params. */
void SetParameters(const RTCPSchedulerParams &params) { schedparams = params; }
/** Returns the currently used scheduler parameters. */
RTCPSchedulerParams GetParameters() const { return schedparams; }
/** Sets the header overhead from underlying protocols (for example UDP and IP) to \c numbytes. */
void SetHeaderOverhead(size_t numbytes) { headeroverhead = numbytes; }
/** Returns the currently used header overhead. */
size_t GetHeaderOverhead() const { return headeroverhead; }
/** For each incoming RTCP compound packet, this function has to be called for the scheduler to work correctly. */
void AnalyseIncoming(RTCPCompoundPacket &rtcpcomppack);
/** For each outgoing RTCP compound packet, this function has to be called for the scheduler to work correctly. */
void AnalyseOutgoing(RTCPCompoundPacket &rtcpcomppack);
/** This function has to be called each time a member times out or sends a BYE packet. */
void ActiveMemberDecrease();
/** Asks the scheduler to schedule an RTCP compound packet containing a BYE packetl; the compound packet
* has size \c packetsize.
*/
void ScheduleBYEPacket(size_t packetsize);
/** Returns the delay after which an RTCP compound will possibly have to be sent.
* Returns the delay after which an RTCP compound will possibly have to be sent. The IsTime member function
* should be called afterwards to make sure that it actually is time to send an RTCP compound packet.
*/
RTPTime GetTransmissionDelay();
/** This function returns \c true if it's time to send an RTCP compound packet and \c false otherwise.
* This function returns \c true if it's time to send an RTCP compound packet and \c false otherwise.
* If the function returns \c true, it will also have calculated the next time at which a packet should
* be sent, so if it is called again right away, it will return \c false.
*/
bool IsTime();
/** Calculates the deterministic interval at this time.
* Calculates the deterministic interval at this time. This is used - in combination with a certain multiplier -
* to time out members, senders etc.
*/
RTPTime CalculateDeterministicInterval(bool sender = false);
private:
void CalculateNextRTCPTime();
void PerformReverseReconsideration();
RTPTime CalculateBYETransmissionInterval();
RTPTime CalculateTransmissionInterval(bool sender);
RTPSources &sources;
RTCPSchedulerParams schedparams;
size_t headeroverhead;
size_t avgrtcppacksize;
bool hassentrtcp;
bool firstcall;
RTPTime nextrtcptime;
RTPTime prevrtcptime;
int pmembers;
// for BYE packet scheduling
bool byescheduled;
int byemembers,pbyemembers;
size_t avgbyepacketsize;
bool sendbyenow;
RTPRandom &rtprand;
};
} // end namespace
#endif // RTCPSCHEDULER_H

View File

@@ -0,0 +1,182 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpsdesinfo.h"
#include "rtpdebug.h"
namespace jrtplib
{
void RTCPSDESInfo::Clear()
{
#ifdef RTP_SUPPORT_SDESPRIV
std::list<SDESPrivateItem *>::const_iterator it;
for (it = privitems.begin() ; it != privitems.end() ; ++it)
RTPDelete(*it,GetMemoryManager());
privitems.clear();
#endif // RTP_SUPPORT_SDESPRIV
}
#ifdef RTP_SUPPORT_SDESPRIV
int RTCPSDESInfo::SetPrivateValue(const uint8_t *prefix,size_t prefixlen,const uint8_t *value,size_t valuelen)
{
std::list<SDESPrivateItem *>::const_iterator it;
bool found;
found = false;
it = privitems.begin();
while (!found && it != privitems.end())
{
uint8_t *p;
size_t l;
p = (*it)->GetPrefix(&l);
if (l == prefixlen)
{
if (l <= 0)
found = true;
else if (memcmp(prefix,p,l) == 0)
found = true;
else
++it;
}
else
++it;
}
SDESPrivateItem *item;
if (found) // replace the value for this entry
item = *it;
else // no entry for this prefix found... add it
{
if (privitems.size() >= RTP_MAXPRIVITEMS) // too many items present, just ignore it
return ERR_RTP_SDES_MAXPRIVITEMS;
int status;
item = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_SDESPRIVATEITEM) SDESPrivateItem(GetMemoryManager());
if (item == 0)
return ERR_RTP_OUTOFMEM;
if ((status = item->SetPrefix(prefix,prefixlen)) < 0)
{
RTPDelete(item,GetMemoryManager());
return status;
}
privitems.push_front(item);
}
return item->SetInfo(value,valuelen);
}
int RTCPSDESInfo::DeletePrivatePrefix(const uint8_t *prefix,size_t prefixlen)
{
std::list<SDESPrivateItem *>::iterator it;
bool found;
found = false;
it = privitems.begin();
while (!found && it != privitems.end())
{
uint8_t *p;
size_t l;
p = (*it)->GetPrefix(&l);
if (l == prefixlen)
{
if (l <= 0)
found = true;
else if (memcmp(prefix,p,l) == 0)
found = true;
else
++it;
}
else
++it;
}
if (!found)
return ERR_RTP_SDES_PREFIXNOTFOUND;
RTPDelete(*it,GetMemoryManager());
privitems.erase(it);
return 0;
}
void RTCPSDESInfo::GotoFirstPrivateValue()
{
curitem = privitems.begin();
}
bool RTCPSDESInfo::GetNextPrivateValue(uint8_t **prefix,size_t *prefixlen,uint8_t **value,size_t *valuelen)
{
if (curitem == privitems.end())
return false;
*prefix = (*curitem)->GetPrefix(prefixlen);
*value = (*curitem)->GetInfo(valuelen);
++curitem;
return true;
}
bool RTCPSDESInfo::GetPrivateValue(const uint8_t *prefix,size_t prefixlen,uint8_t **value,size_t *valuelen) const
{
std::list<SDESPrivateItem *>::const_iterator it;
bool found;
found = false;
it = privitems.begin();
while (!found && it != privitems.end())
{
uint8_t *p;
size_t l;
p = (*it)->GetPrefix(&l);
if (l == prefixlen)
{
if (l <= 0)
found = true;
else if (memcmp(prefix,p,l) == 0)
found = true;
else
++it;
}
else
++it;
}
if (found)
*value = (*it)->GetInfo(valuelen);
return found;
}
#endif // RTP_SUPPORT_SDESPRIV
} // end namespace

View File

@@ -0,0 +1,220 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpsdesinfo.h
*/
#ifndef RTCPSDESINFO_H
#define RTCPSDESINFO_H
#include "rtpconfig.h"
#include "rtperrors.h"
#include "rtpdefines.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
#include <string.h>
#include <list>
namespace jrtplib
{
/** The class RTCPSDESInfo is a container for RTCP SDES information. */
class JRTPLIB_IMPORTEXPORT RTCPSDESInfo : public RTPMemoryObject
{
public:
/** Constructs an instance, optionally installing a memory manager. */
RTCPSDESInfo(RTPMemoryManager *mgr = 0) : RTPMemoryObject(mgr) { for (int i = 0 ; i < RTCP_SDES_NUMITEMS_NONPRIVATE ; i++) nonprivateitems[i].SetMemoryManager(mgr); }
virtual ~RTCPSDESInfo() { Clear(); }
/** Clears all SDES information. */
void Clear();
/** Sets the SDES CNAME item to \c s with length \c l. */
int SetCNAME(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_CNAME-1,s,l); }
/** Sets the SDES name item to \c s with length \c l. */
int SetName(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_NAME-1,s,l); }
/** Sets the SDES e-mail item to \c s with length \c l. */
int SetEMail(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_EMAIL-1,s,l); }
/** Sets the SDES phone item to \c s with length \c l. */
int SetPhone(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_PHONE-1,s,l); }
/** Sets the SDES location item to \c s with length \c l. */
int SetLocation(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_LOCATION-1,s,l); }
/** Sets the SDES tool item to \c s with length \c l. */
int SetTool(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_TOOL-1,s,l); }
/** Sets the SDES note item to \c s with length \c l. */
int SetNote(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_NOTE-1,s,l); }
#ifdef RTP_SUPPORT_SDESPRIV
/** Sets the entry for the prefix string specified by \c prefix with length \c prefixlen to contain
* the value string specified by \c value with length \c valuelen (if the maximum allowed
* number of prefixes was reached, the error code \c ERR_RTP_SDES_MAXPRIVITEMS is returned.
*/
int SetPrivateValue(const uint8_t *prefix,size_t prefixlen,const uint8_t *value,size_t valuelen);
/** Deletes the entry for the prefix specified by \c s with length \c len. */
int DeletePrivatePrefix(const uint8_t *s,size_t len);
#endif // RTP_SUPPORT_SDESPRIV
/** Returns the SDES CNAME item and stores its length in \c len. */
uint8_t *GetCNAME(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_CNAME-1,len); }
/** Returns the SDES name item and stores its length in \c len. */
uint8_t *GetName(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_NAME-1,len); }
/** Returns the SDES e-mail item and stores its length in \c len. */
uint8_t *GetEMail(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_EMAIL-1,len); }
/** Returns the SDES phone item and stores its length in \c len. */
uint8_t *GetPhone(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_PHONE-1,len); }
/** Returns the SDES location item and stores its length in \c len. */
uint8_t *GetLocation(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_LOCATION-1,len); }
/** Returns the SDES tool item and stores its length in \c len. */
uint8_t *GetTool(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_TOOL-1,len); }
/** Returns the SDES note item and stores its length in \c len. */
uint8_t *GetNote(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_NOTE-1,len); }
#ifdef RTP_SUPPORT_SDESPRIV
/** Starts the iteration over the stored SDES private item prefixes and their associated values. */
void GotoFirstPrivateValue();
/** Returns SDES priv item information.
* If available, returns \c true and stores the next SDES
* private item prefix in \c prefix and its length in
* \c prefixlen. The associated value and its length are
* then stored in \c value and \c valuelen. Otherwise,
* it returns \c false.
*/
bool GetNextPrivateValue(uint8_t **prefix,size_t *prefixlen,uint8_t **value,size_t *valuelen);
/** Returns SDES priv item information.
* Looks for the entry which corresponds to the SDES private
* item prefix \c prefix with length \c prefixlen. If found,
* the function returns \c true and stores the associated
* value and its length in \c value and \c valuelen
* respectively.
*/
bool GetPrivateValue(const uint8_t *prefix,size_t prefixlen,uint8_t **value,size_t *valuelen) const;
#endif // RTP_SUPPORT_SDESPRIV
private:
int SetNonPrivateItem(int itemno,const uint8_t *s,size_t l) { if (l > RTCP_SDES_MAXITEMLENGTH) return ERR_RTP_SDES_LENGTHTOOBIG; return nonprivateitems[itemno].SetInfo(s,l); }
uint8_t *GetNonPrivateItem(int itemno,size_t *len) const { return nonprivateitems[itemno].GetInfo(len); }
class SDESItem : public RTPMemoryObject
{
public:
SDESItem(RTPMemoryManager *mgr = 0) : RTPMemoryObject(mgr)
{
str = 0;
length = 0;
}
void SetMemoryManager(RTPMemoryManager *mgr)
{
RTPMemoryObject::SetMemoryManager(mgr);
}
~SDESItem()
{
if (str)
RTPDeleteByteArray(str,GetMemoryManager());
}
uint8_t *GetInfo(size_t *len) const { *len = length; return str; }
int SetInfo(const uint8_t *s,size_t len) { return SetString(&str,&length,s,len); }
protected:
int SetString(uint8_t **dest,size_t *destlen,const uint8_t *s,size_t len)
{
if (len <= 0)
{
if (*dest)
RTPDeleteByteArray((*dest),GetMemoryManager());
*dest = 0;
*destlen = 0;
}
else
{
len = (len>RTCP_SDES_MAXITEMLENGTH)?RTCP_SDES_MAXITEMLENGTH:len;
uint8_t *str2 = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_SDESITEM) uint8_t[len];
if (str2 == 0)
return ERR_RTP_OUTOFMEM;
memcpy(str2,s,len);
*destlen = len;
if (*dest)
RTPDeleteByteArray((*dest),GetMemoryManager());
*dest = str2;
}
return 0;
}
private:
uint8_t *str;
size_t length;
};
SDESItem nonprivateitems[RTCP_SDES_NUMITEMS_NONPRIVATE];
#ifdef RTP_SUPPORT_SDESPRIV
class SDESPrivateItem : public SDESItem
{
public:
SDESPrivateItem(RTPMemoryManager *mgr) : SDESItem(mgr)
{
prefixlen = 0;
prefix = 0;
}
~SDESPrivateItem()
{
if (prefix)
RTPDeleteByteArray(prefix,GetMemoryManager());
}
uint8_t *GetPrefix(size_t *len) const { *len = prefixlen; return prefix; }
int SetPrefix(const uint8_t *s,size_t len) { return SetString(&prefix,&prefixlen,s,len); }
private:
uint8_t *prefix;
size_t prefixlen;
};
std::list<SDESPrivateItem *> privitems;
std::list<SDESPrivateItem *>::const_iterator curitem;
#endif // RTP_SUPPORT_SDESPRIV
};
} // end namespace
#endif // RTCPSDESINFO_H

View File

@@ -0,0 +1,236 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpsdespacket.h"
#ifdef RTPDEBUG
#include <iostream>
#include <string.h>
#endif // RTPDEBUG
#include "rtpdebug.h"
namespace jrtplib
{
RTCPSDESPacket::RTCPSDESPacket(uint8_t *data,size_t datalength)
: RTCPPacket(SDES,data,datalength)
{
knownformat = false;
currentchunk = 0;
itemoffset = 0;
curchunknum = 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
size_t len = datalength;
if (hdr->padding)
{
uint8_t padcount = data[datalength-1];
if ((padcount & 0x03) != 0) // not a multiple of four! (see rfc 3550 p 37)
return;
if (((size_t)padcount) >= len)
return;
len -= (size_t)padcount;
}
if (hdr->count == 0)
{
if (len != sizeof(RTCPCommonHeader))
return;
}
else
{
int ssrccount = (int)(hdr->count);
uint8_t *chunk;
int chunkoffset;
if (len < sizeof(RTCPCommonHeader))
return;
len -= sizeof(RTCPCommonHeader);
chunk = data+sizeof(RTCPCommonHeader);
while ((ssrccount > 0) && (len > 0))
{
chunkoffset = 0;
if (len < (sizeof(uint32_t)*2)) // chunk must contain at least a SSRC identifier
return; // and a (possibly empty) item
len -= sizeof(uint32_t);
chunkoffset = sizeof(uint32_t);
bool done = false;
while (!done)
{
if (len < 1) // at least a zero byte (end of item list) should be there
return;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(chunk+chunkoffset);
if (sdeshdr->sdesid == 0) // end of item list
{
len--;
chunkoffset++;
size_t r = (chunkoffset&0x03);
if (r != 0)
{
size_t addoffset = 4-r;
if (addoffset > len)
return;
len -= addoffset;
chunkoffset += addoffset;
}
done = true;
}
else
{
if (len < sizeof(RTCPSDESHeader))
return;
len -= sizeof(RTCPSDESHeader);
chunkoffset += sizeof(RTCPSDESHeader);
size_t itemlen = (size_t)(sdeshdr->length);
if (itemlen > len)
return;
len -= itemlen;
chunkoffset += itemlen;
}
}
ssrccount--;
chunk += chunkoffset;
}
// check for remaining bytes
if (len > 0)
return;
if (ssrccount > 0)
return;
}
knownformat = true;
}
#ifdef RTPDEBUG
void RTCPSDESPacket::Dump()
{
RTCPPacket::Dump();
if (!IsKnownFormat())
{
std::cout << " Unknown format" << std::endl;
return;
}
if (!GotoFirstChunk())
{
std::cout << " No chunks present" << std::endl;
return;
}
do
{
std::cout << " SDES Chunk for SSRC: " << GetChunkSSRC() << std::endl;
if (!GotoFirstItem())
std::cout << " No items found" << std::endl;
else
{
do
{
std::cout << " ";
switch (GetItemType())
{
case None:
std::cout << "None ";
break;
case CNAME:
std::cout << "CNAME ";
break;
case NAME:
std::cout << "NAME ";
break;
case EMAIL:
std::cout << "EMAIL ";
break;
case PHONE:
std::cout << "PHONE ";
break;
case LOC:
std::cout << "LOC ";
break;
case TOOL:
std::cout << "TOOL ";
break;
case NOTE:
std::cout << "NOTE ";
break;
case PRIV:
std::cout << "PRIV ";
break;
case Unknown:
default:
std::cout << "Unknown ";
}
std::cout << "Length: " << GetItemLength() << std::endl;
if (GetItemType() != PRIV)
{
char str[1024];
memcpy(str,GetItemData(),GetItemLength());
str[GetItemLength()] = 0;
std::cout << " Value: " << str << std::endl;
}
#ifdef RTP_SUPPORT_SDESPRIV
else // PRIV item
{
char str[1024];
memcpy(str,GetPRIVPrefixData(),GetPRIVPrefixLength());
str[GetPRIVPrefixLength()] = 0;
std::cout << " Prefix: " << str << std::endl;
std::cout << " Length: " << GetPRIVPrefixLength() << std::endl;
memcpy(str,GetPRIVValueData(),GetPRIVValueLength());
str[GetPRIVValueLength()] = 0;
std::cout << " Value: " << str << std::endl;
std::cout << " Length: " << GetPRIVValueLength() << std::endl;
}
#endif // RTP_SUPPORT_SDESPRIV
} while (GotoNextItem());
}
} while (GotoNextChunk());
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,386 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpsdespacket.h
*/
#ifndef RTCPSDESPACKET_H
#define RTCPSDESPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
#include "rtpstructs.h"
#include "rtpdefines.h"
#if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h>
#endif // WIN32
namespace jrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP source description packet. */
class JRTPLIB_IMPORTEXPORT RTCPSDESPacket : public RTCPPacket
{
public:
/** Identifies the type of an SDES item. */
enum ItemType
{
None, /**< Used when the iteration over the items has finished. */
CNAME, /**< Used for a CNAME (canonical name) item. */
NAME, /**< Used for a NAME item. */
EMAIL, /**< Used for an EMAIL item. */
PHONE, /**< Used for a PHONE item. */
LOC, /**< Used for a LOC (location) item. */
TOOL, /**< Used for a TOOL item. */
NOTE, /**< Used for a NOTE item. */
PRIV, /**< Used for a PRIV item. */
Unknown /**< Used when there is an item present, but the type is not recognized. */
};
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it
* points to is valid as long as the class instance exists.
*/
RTCPSDESPacket(uint8_t *data,size_t datalen);
~RTCPSDESPacket() { }
/** Returns the number of SDES chunks in the SDES packet.
* Returns the number of SDES chunks in the SDES packet. Each chunk has its own SSRC identifier.
*/
int GetChunkCount() const;
/** Starts the iteration over the chunks.
* Starts the iteration. If no SDES chunks are present, the function returns \c false. Otherwise,
* it returns \c true and sets the current chunk to be the first chunk.
*/
bool GotoFirstChunk();
/** Sets the current chunk to the next available chunk.
* Sets the current chunk to the next available chunk. If no next chunk is present, this function returns
* \c false, otherwise it returns \c true.
*/
bool GotoNextChunk();
/** Returns the SSRC identifier of the current chunk. */
uint32_t GetChunkSSRC() const;
/** Starts the iteration over the SDES items in the current chunk.
* Starts the iteration over the SDES items in the current chunk. If no SDES items are
* present, the function returns \c false. Otherwise, the function sets the current item
* to be the first one and returns \c true.
*/
bool GotoFirstItem();
/** Advances the iteration to the next item in the current chunk.
* If there's another item in the chunk, the current item is set to be the next one and the function
* returns \c true. Otherwise, the function returns \c false.
*/
bool GotoNextItem();
/** Returns the SDES item type of the current item in the current chunk. */
ItemType GetItemType() const;
/** Returns the item length of the current item in the current chunk. */
size_t GetItemLength() const;
/** Returns the item data of the current item in the current chunk. */
uint8_t *GetItemData();
#ifdef RTP_SUPPORT_SDESPRIV
/** If the current item is an SDES PRIV item, this function returns the length of the
* prefix string of the private item.
*/
size_t GetPRIVPrefixLength() const;
/** If the current item is an SDES PRIV item, this function returns actual data of the
* prefix string.
*/
uint8_t *GetPRIVPrefixData();
/** If the current item is an SDES PRIV item, this function returns the length of the
* value string of the private item.
*/
size_t GetPRIVValueLength() const;
/** If the current item is an SDES PRIV item, this function returns actual value data of the
* private item.
*/
uint8_t *GetPRIVValueData();
#endif // RTP_SUPPORT_SDESPRIV
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
private:
uint8_t *currentchunk;
int curchunknum;
size_t itemoffset;
};
inline int RTCPSDESPacket::GetChunkCount() const
{
if (!knownformat)
return 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
return ((int)hdr->count);
}
inline bool RTCPSDESPacket::GotoFirstChunk()
{
if (GetChunkCount() == 0)
{
currentchunk = 0;
return false;
}
currentchunk = data+sizeof(RTCPCommonHeader);
curchunknum = 1;
itemoffset = sizeof(uint32_t);
return true;
}
inline bool RTCPSDESPacket::GotoNextChunk()
{
if (!knownformat)
return false;
if (currentchunk == 0)
return false;
if (curchunknum == GetChunkCount())
return false;
size_t offset = sizeof(uint32_t);
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+sizeof(uint32_t));
while (sdeshdr->sdesid != 0)
{
offset += sizeof(RTCPSDESHeader);
offset += (size_t)(sdeshdr->length);
sdeshdr = (RTCPSDESHeader *)(currentchunk+offset);
}
offset++; // for the zero byte
if ((offset&0x03) != 0)
offset += (4-(offset&0x03));
currentchunk += offset;
curchunknum++;
itemoffset = sizeof(uint32_t);
return true;
}
inline uint32_t RTCPSDESPacket::GetChunkSSRC() const
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
uint32_t *ssrc = (uint32_t *)currentchunk;
return ntohl(*ssrc);
}
inline bool RTCPSDESPacket::GotoFirstItem()
{
if (!knownformat)
return false;
if (currentchunk == 0)
return false;
itemoffset = sizeof(uint32_t);
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid == 0)
return false;
return true;
}
inline bool RTCPSDESPacket::GotoNextItem()
{
if (!knownformat)
return false;
if (currentchunk == 0)
return false;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid == 0)
return false;
size_t offset = itemoffset;
offset += sizeof(RTCPSDESHeader);
offset += (size_t)(sdeshdr->length);
sdeshdr = (RTCPSDESHeader *)(currentchunk+offset);
if (sdeshdr->sdesid == 0)
return false;
itemoffset = offset;
return true;
}
inline RTCPSDESPacket::ItemType RTCPSDESPacket::GetItemType() const
{
if (!knownformat)
return None;
if (currentchunk == 0)
return None;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
switch (sdeshdr->sdesid)
{
case 0:
return None;
case RTCP_SDES_ID_CNAME:
return CNAME;
case RTCP_SDES_ID_NAME:
return NAME;
case RTCP_SDES_ID_EMAIL:
return EMAIL;
case RTCP_SDES_ID_PHONE:
return PHONE;
case RTCP_SDES_ID_LOCATION:
return LOC;
case RTCP_SDES_ID_TOOL:
return TOOL;
case RTCP_SDES_ID_NOTE:
return NOTE;
case RTCP_SDES_ID_PRIVATE:
return PRIV;
default:
return Unknown;
}
return Unknown;
}
inline size_t RTCPSDESPacket::GetItemLength() const
{
if (!knownformat)
return None;
if (currentchunk == 0)
return None;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid == 0)
return 0;
return (size_t)(sdeshdr->length);
}
inline uint8_t *RTCPSDESPacket::GetItemData()
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid == 0)
return 0;
return (currentchunk+itemoffset+sizeof(RTCPSDESHeader));
}
#ifdef RTP_SUPPORT_SDESPRIV
inline size_t RTCPSDESPacket::GetPRIVPrefixLength() const
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid != RTCP_SDES_ID_PRIVATE)
return 0;
if (sdeshdr->length == 0)
return 0;
uint8_t *preflen = currentchunk+itemoffset+sizeof(RTCPSDESHeader);
size_t prefixlength = (size_t)(*preflen);
if (prefixlength > (size_t)((sdeshdr->length)-1))
return 0;
return prefixlength;
}
inline uint8_t *RTCPSDESPacket::GetPRIVPrefixData()
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid != RTCP_SDES_ID_PRIVATE)
return 0;
if (sdeshdr->length == 0)
return 0;
uint8_t *preflen = currentchunk+itemoffset+sizeof(RTCPSDESHeader);
size_t prefixlength = (size_t)(*preflen);
if (prefixlength > (size_t)((sdeshdr->length)-1))
return 0;
if (prefixlength == 0)
return 0;
return (currentchunk+itemoffset+sizeof(RTCPSDESHeader)+1);
}
inline size_t RTCPSDESPacket::GetPRIVValueLength() const
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid != RTCP_SDES_ID_PRIVATE)
return 0;
if (sdeshdr->length == 0)
return 0;
uint8_t *preflen = currentchunk+itemoffset+sizeof(RTCPSDESHeader);
size_t prefixlength = (size_t)(*preflen);
if (prefixlength > (size_t)((sdeshdr->length)-1))
return 0;
return ((size_t)(sdeshdr->length))-prefixlength-1;
}
inline uint8_t *RTCPSDESPacket::GetPRIVValueData()
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid != RTCP_SDES_ID_PRIVATE)
return 0;
if (sdeshdr->length == 0)
return 0;
uint8_t *preflen = currentchunk+itemoffset+sizeof(RTCPSDESHeader);
size_t prefixlength = (size_t)(*preflen);
if (prefixlength > (size_t)((sdeshdr->length)-1))
return 0;
size_t valuelen = ((size_t)(sdeshdr->length))-prefixlength-1;
if (valuelen == 0)
return 0;
return (currentchunk+itemoffset+sizeof(RTCPSDESHeader)+1+prefixlength);
}
#endif // RTP_SUPPORT_SDESPRIV
} // end namespace
#endif // RTCPSDESPACKET_H

View File

@@ -0,0 +1,106 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpsrpacket.h"
#ifdef RTPDEBUG
#include <iostream>
#endif // RTPDEBUG
#include "rtpdebug.h"
namespace jrtplib
{
RTCPSRPacket::RTCPSRPacket(uint8_t *data,size_t datalength)
: RTCPPacket(SR,data,datalength)
{
knownformat = false;
RTCPCommonHeader *hdr;
size_t len = datalength;
size_t expectedlength;
hdr = (RTCPCommonHeader *)data;
if (hdr->padding)
{
uint8_t padcount = data[datalength-1];
if ((padcount & 0x03) != 0) // not a multiple of four! (see rfc 3550 p 37)
return;
if (((size_t)padcount) >= len)
return;
len -= (size_t)padcount;
}
expectedlength = sizeof(RTCPCommonHeader)+sizeof(uint32_t)+sizeof(RTCPSenderReport);
expectedlength += sizeof(RTCPReceiverReport)*((int)hdr->count);
if (expectedlength != len)
return;
knownformat = true;
}
#ifdef RTPDEBUG
void RTCPSRPacket::Dump()
{
RTCPPacket::Dump();
if (!IsKnownFormat())
std::cout << " Unknown format" << std::endl;
else
{
int num = GetReceptionReportCount();
int i;
RTPNTPTime t = GetNTPTimestamp();
std::cout << " SSRC of sender: " << GetSenderSSRC() << std::endl;
std::cout << " Sender info:" << std::endl;
std::cout << " NTP timestamp: " << t.GetMSW() << ":" << t.GetLSW() << std::endl;
std::cout << " RTP timestamp: " << GetRTPTimestamp() << std::endl;
std::cout << " Packet count: " << GetSenderPacketCount() << std::endl;
std::cout << " Octet count: " << GetSenderOctetCount() << std::endl;
for (i = 0 ; i < num ; i++)
{
std::cout << " Report block " << i << std::endl;
std::cout << " SSRC: " << GetSSRC(i) << std::endl;
std::cout << " Fraction lost: " << (uint32_t)GetFractionLost(i) << std::endl;
std::cout << " Packets lost: " << GetLostPacketCount(i) << std::endl;
std::cout << " Seq. nr.: " << GetExtendedHighestSequenceNumber(i) << std::endl;
std::cout << " Jitter: " << GetJitter(i) << std::endl;
std::cout << " LSR: " << GetLSR(i) << std::endl;
std::cout << " DLSR: " << GetDLSR(i) << std::endl;
}
}
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,252 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpsrpacket.h
*/
#ifndef RTCPSRPACKET_H
#define RTCPSRPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
#include "rtptimeutilities.h"
#include "rtpstructs.h"
#if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h>
#endif // WIN32
namespace jrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP sender report packet. */
class JRTPLIB_IMPORTEXPORT RTCPSRPacket : public RTCPPacket
{
public:
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it
* points to is valid as long as the class instance exists.
*/
RTCPSRPacket(uint8_t *data,size_t datalength);
~RTCPSRPacket() { }
/** Returns the SSRC of the participant who sent this packet. */
uint32_t GetSenderSSRC() const;
/** Returns the NTP timestamp contained in the sender report. */
RTPNTPTime GetNTPTimestamp() const;
/** Returns the RTP timestamp contained in the sender report. */
uint32_t GetRTPTimestamp() const;
/** Returns the sender's packet count contained in the sender report. */
uint32_t GetSenderPacketCount() const;
/** Returns the sender's octet count contained in the sender report. */
uint32_t GetSenderOctetCount() const;
/** Returns the number of reception report blocks present in this packet. */
int GetReceptionReportCount() const;
/** Returns the SSRC of the reception report block described by \c index which may have a value
* from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetSSRC(int index) const;
/** Returns the `fraction lost' field of the reception report described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint8_t GetFractionLost(int index) const;
/** Returns the number of lost packets in the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
int32_t GetLostPacketCount(int index) const;
/** Returns the extended highest sequence number of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetExtendedHighestSequenceNumber(int index) const;
/** Returns the jitter field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetJitter(int index) const;
/** Returns the LSR field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetLSR(int index) const;
/** Returns the DLSR field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetDLSR(int index) const;
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
private:
RTCPReceiverReport *GotoReport(int index) const;
};
inline uint32_t RTCPSRPacket::GetSenderSSRC() const
{
if (!knownformat)
return 0;
uint32_t *ssrcptr = (uint32_t *)(data+sizeof(RTCPCommonHeader));
return ntohl(*ssrcptr);
}
inline RTPNTPTime RTCPSRPacket::GetNTPTimestamp() const
{
if (!knownformat)
return RTPNTPTime(0,0);
RTCPSenderReport *sr = (RTCPSenderReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t));
return RTPNTPTime(ntohl(sr->ntptime_msw),ntohl(sr->ntptime_lsw));
}
inline uint32_t RTCPSRPacket::GetRTPTimestamp() const
{
if (!knownformat)
return 0;
RTCPSenderReport *sr = (RTCPSenderReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t));
return ntohl(sr->rtptimestamp);
}
inline uint32_t RTCPSRPacket::GetSenderPacketCount() const
{
if (!knownformat)
return 0;
RTCPSenderReport *sr = (RTCPSenderReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t));
return ntohl(sr->packetcount);
}
inline uint32_t RTCPSRPacket::GetSenderOctetCount() const
{
if (!knownformat)
return 0;
RTCPSenderReport *sr = (RTCPSenderReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t));
return ntohl(sr->octetcount);
}
inline int RTCPSRPacket::GetReceptionReportCount() const
{
if (!knownformat)
return 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
return ((int)hdr->count);
}
inline RTCPReceiverReport *RTCPSRPacket::GotoReport(int index) const
{
RTCPReceiverReport *r = (RTCPReceiverReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t)+sizeof(RTCPSenderReport)+index*sizeof(RTCPReceiverReport));
return r;
}
inline uint32_t RTCPSRPacket::GetSSRC(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->ssrc);
}
inline uint8_t RTCPSRPacket::GetFractionLost(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return r->fractionlost;
}
inline int32_t RTCPSRPacket::GetLostPacketCount(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
uint32_t count = ((uint32_t)r->packetslost[2])|(((uint32_t)r->packetslost[1])<<8)|(((uint32_t)r->packetslost[0])<<16);
if ((count&0x00800000) != 0) // test for negative number
count |= 0xFF000000;
int32_t *count2 = (int32_t *)(&count);
return (*count2);
}
inline uint32_t RTCPSRPacket::GetExtendedHighestSequenceNumber(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->exthighseqnr);
}
inline uint32_t RTCPSRPacket::GetJitter(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->jitter);
}
inline uint32_t RTCPSRPacket::GetLSR(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->lsr);
}
inline uint32_t RTCPSRPacket::GetDLSR(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->dlsr);
}
} // end namespace
#endif // RTCPSRPACKET_H

View File

@@ -0,0 +1,73 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpunknownpacket.h
*/
#ifndef RTCPUNKNOWNPACKET_H
#define RTCPUNKNOWNPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
namespace jrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP packet of unknown type.
* Describes an RTCP packet of unknown type. This class doesn't have any extra member functions besides
* the ones it inherited. Note that since an unknown packet type doesn't have any format to check
* against, the IsKnownFormat function will trivially return \c true.
*/
class JRTPLIB_IMPORTEXPORT RTCPUnknownPacket : public RTCPPacket
{
public:
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it
* points to is valid as long as the class instance exists.
*/
RTCPUnknownPacket(uint8_t *data,size_t datalen) : RTCPPacket(Unknown,data,datalen)
{
// Since we don't expect a format, we'll trivially put knownformat = true
knownformat = true;
}
~RTCPUnknownPacket() { }
};
} // end namespace
#endif // RTCPUNKNOWNPACKET_H

View File

@@ -0,0 +1,99 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpaddress.h
*/
#ifndef RTPADDRESS_H
#define RTPADDRESS_H
#include "rtpconfig.h"
#include <string>
namespace jrtplib
{
class RTPMemoryManager;
/** This class is an abstract class which is used to specify destinations, multicast groups etc. */
class JRTPLIB_IMPORTEXPORT RTPAddress
{
public:
/** Identifies the actual implementation being used. */
enum AddressType
{
IPv4Address, /**< Used by the UDP over IPv4 transmitter. */
IPv6Address, /**< Used by the UDP over IPv6 transmitter. */
ByteAddress, /**< A very general type of address, consisting of a port number and a number of bytes representing the host address. */
UserDefinedAddress /**< Can be useful for a user-defined transmitter. */
};
/** Returns the type of address the actual implementation represents. */
AddressType GetAddressType() const { return addresstype; }
/** Creates a copy of the RTPAddress instance.
* Creates a copy of the RTPAddress instance. If \c mgr is not NULL, the
* corresponding memory manager will be used to allocate the memory for the address
* copy.
*/
virtual RTPAddress *CreateCopy(RTPMemoryManager *mgr) const = 0;
/** Checks if the address \c addr is the same address as the one this instance represents.
* Checks if the address \c addr is the same address as the one this instance represents.
* Implementations must be able to handle a NULL argument.
*/
virtual bool IsSameAddress(const RTPAddress *addr) const = 0;
/** Checks if the address \c addr represents the same host as this instance.
* Checks if the address \c addr represents the same host as this instance. Implementations
* must be able to handle a NULL argument.
*/
virtual bool IsFromSameHost(const RTPAddress *addr) const = 0;
#ifdef RTPDEBUG
virtual std::string GetAddressString() const = 0;
#endif // RTPDEBUG
virtual ~RTPAddress() { }
protected:
// only allow subclasses to be created
RTPAddress(const AddressType t) : addresstype(t) { }
private:
const AddressType addresstype;
};
} // end namespace
#endif // RTPADDRESS_H

View File

@@ -0,0 +1,105 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpbyteaddress.h"
#include "rtpmemorymanager.h"
#ifdef RTPDEBUG
#include "rtpdefines.h"
#include <stdio.h>
#endif // RTPDEBUG
namespace jrtplib
{
bool RTPByteAddress::IsSameAddress(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != ByteAddress)
return false;
const RTPByteAddress *addr2 = (const RTPByteAddress *)addr;
if (addr2->addresslength != addresslength)
return false;
if (addresslength == 0 || (memcmp(hostaddress, addr2->hostaddress, addresslength) == 0))
{
if (port == addr2->port)
return true;
}
return false;
}
bool RTPByteAddress::IsFromSameHost(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != ByteAddress)
return false;
const RTPByteAddress *addr2 = (const RTPByteAddress *)addr;
if (addr2->addresslength != addresslength)
return false;
if (addresslength == 0 || (memcmp(hostaddress, addr2->hostaddress, addresslength) == 0))
return true;
return false;
}
RTPAddress *RTPByteAddress::CreateCopy(RTPMemoryManager *mgr) const
{
RTPByteAddress *a = RTPNew(mgr, RTPMEM_TYPE_CLASS_RTPADDRESS) RTPByteAddress(hostaddress, addresslength, port);
return a;
}
#ifdef RTPDEBUG
std::string RTPByteAddress::GetAddressString() const
{
char str[16];
std::string s;
for (int i = 0 ; i < addresslength ; i++)
{
RTP_SNPRINTF(str, 16, "%02X", (int)hostaddress[i]);
s += std::string(str);
}
s += std::string(":");
RTP_SNPRINTF(str, 16, "%d",(int)port);
s += std::string(str);
return s;
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,93 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpbyteaddress.h
*/
#ifndef RTPBYTEADDRESS_H
#define RTPBYTEADDRESS_H
#include "rtpconfig.h"
#include "rtpaddress.h"
#include "rtptypes.h"
#include <string.h>
#define RTPBYTEADDRESS_MAXLENGTH 128
namespace jrtplib
{
class RTPMemoryManager;
/** A very general kind of address consisting of a port number and a number of bytes describing the host address.
* A very general kind of address, consisting of a port number and a number of bytes describing the host address.
*/
class JRTPLIB_IMPORTEXPORT RTPByteAddress : public RTPAddress
{
public:
/** Creates an instance of the class using \c addrlen bytes of \c hostaddress as host identification,
* and using \c port as the port number. */
RTPByteAddress(const uint8_t hostaddress[RTPBYTEADDRESS_MAXLENGTH], size_t addrlen, uint16_t port = 0) : RTPAddress(ByteAddress) { if (addrlen > RTPBYTEADDRESS_MAXLENGTH) addrlen = RTPBYTEADDRESS_MAXLENGTH; memcpy(RTPByteAddress::hostaddress, hostaddress, addrlen); RTPByteAddress::addresslength = addrlen; RTPByteAddress::port = port; }
/** Sets the host address to the first \c addrlen bytes of \c hostaddress. */
void SetHostAddress(const uint8_t hostaddress[RTPBYTEADDRESS_MAXLENGTH], size_t addrlen) { if (addrlen > RTPBYTEADDRESS_MAXLENGTH) addrlen = RTPBYTEADDRESS_MAXLENGTH; memcpy(RTPByteAddress::hostaddress, hostaddress, addrlen); RTPByteAddress::addresslength = addrlen; }
/** Sets the port number to \c port. */
void SetPort(uint16_t port) { RTPByteAddress::port = port; }
/** Returns a pointer to the stored host address. */
const uint8_t *GetHostAddress() const { return hostaddress; }
/** Returns the length in bytes of the stored host address. */
size_t GetHostAddressLength() const { return addresslength; }
/** Returns the port number stored in this instance. */
uint16_t GetPort() const { return port; }
RTPAddress *CreateCopy(RTPMemoryManager *mgr) const;
bool IsSameAddress(const RTPAddress *addr) const;
bool IsFromSameHost(const RTPAddress *addr) const;
#ifdef RTPDEBUG
std::string GetAddressString() const;
#endif // RTPDEBUG
private:
uint8_t hostaddress[RTPBYTEADDRESS_MAXLENGTH];
size_t addresslength;
uint16_t port;
};
} // end namespace
#endif // RTPBYTEADDRESS_H

View File

@@ -0,0 +1,130 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpcollisionlist.h"
#include "rtperrors.h"
#include "rtpmemorymanager.h"
#ifdef RTPDEBUG
#include <iostream>
#endif // RTPDEBUG
#include "rtpdebug.h"
namespace jrtplib
{
RTPCollisionList::RTPCollisionList(RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
{
#if (defined(WIN32) || defined(_WIN32_WCE))
timeinit.Dummy();
#endif // WIN32 || _WIN32_WCE
}
void RTPCollisionList::Clear()
{
std::list<AddressAndTime>::iterator it;
for (it = addresslist.begin() ; it != addresslist.end() ; it++)
RTPDelete((*it).addr,GetMemoryManager());
addresslist.clear();
}
int RTPCollisionList::UpdateAddress(const RTPAddress *addr,const RTPTime &receivetime,bool *created)
{
if (addr == 0)
return ERR_RTP_COLLISIONLIST_BADADDRESS;
std::list<AddressAndTime>::iterator it;
for (it = addresslist.begin() ; it != addresslist.end() ; it++)
{
if (((*it).addr)->IsSameAddress(addr))
{
(*it).recvtime = receivetime;
*created = false;
return 0;
}
}
RTPAddress *newaddr = addr->CreateCopy(GetMemoryManager());
if (newaddr == 0)
return ERR_RTP_OUTOFMEM;
addresslist.push_back(AddressAndTime(newaddr,receivetime));
*created = true;
return 0;
}
bool RTPCollisionList::HasAddress(const RTPAddress *addr) const
{
std::list<AddressAndTime>::const_iterator it;
for (it = addresslist.begin() ; it != addresslist.end() ; it++)
{
if (((*it).addr)->IsSameAddress(addr))
return true;
}
return false;
}
void RTPCollisionList::Timeout(const RTPTime &currenttime,const RTPTime &timeoutdelay)
{
std::list<AddressAndTime>::iterator it;
RTPTime checktime = currenttime;
checktime -= timeoutdelay;
it = addresslist.begin();
while(it != addresslist.end())
{
if ((*it).recvtime < checktime) // timeout
{
RTPDelete((*it).addr,GetMemoryManager());
it = addresslist.erase(it);
}
else
it++;
}
}
#ifdef RTPDEBUG
void RTPCollisionList::Dump()
{
std::list<AddressAndTime>::const_iterator it;
for (it = addresslist.begin() ; it != addresslist.end() ; it++)
std::cout << "Address: " << ((*it).addr)->GetAddressString() << "\tTime: " << (*it).recvtime.GetSeconds() << std::endl;
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,95 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpcollisionlist.h
*/
#ifndef RTPCOLLISIONLIST_H
#define RTPCOLLISIONLIST_H
#include "rtpconfig.h"
#include "rtpaddress.h"
#include "rtptimeutilities.h"
#include "rtpmemoryobject.h"
#include <list>
namespace jrtplib
{
class RTPAddress;
/** This class represents a list of addresses from which SSRC collisions were detected. */
class JRTPLIB_IMPORTEXPORT RTPCollisionList : public RTPMemoryObject
{
public:
/** Constructs an instance, optionally installing a memory manager. */
RTPCollisionList(RTPMemoryManager *mgr = 0);
~RTPCollisionList() { Clear(); }
/** Clears the list of addresses. */
void Clear();
/** Updates the entry for address \c addr to indicate that a collision was detected at time \c receivetime.
* Updates the entry for address \c addr to indicate that a collision was detected at time \c receivetime.
* If the entry did not exist yet, the flag \c created is set to \c true, otherwise it is set to \c false.
*/
int UpdateAddress(const RTPAddress *addr,const RTPTime &receivetime,bool *created);
/** Returns \c true} if the address \c addr appears in the list. */
bool HasAddress(const RTPAddress *addr) const;
/** Assuming that the current time is given by \c currenttime, this function times out entries which
* haven't been updated in the previous time interval specified by \c timeoutdelay.
*/
void Timeout(const RTPTime &currenttime,const RTPTime &timeoutdelay);
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
private:
class AddressAndTime
{
public:
AddressAndTime(RTPAddress *a,const RTPTime &t) : addr(a),recvtime(t) { }
RTPAddress *addr;
RTPTime recvtime;
};
std::list<AddressAndTime> addresslist;
};
} // end namespace
#endif // RTPCOLLISIONLIST_H

View File

@@ -0,0 +1,76 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPCONFIG_UNIX_H
#define RTPCONFIG_UNIX_H
#define JRTPLIB_IMPORT
#define JRTPLIB_EXPORT
#define JRTPLIB_IMPORTEXPORT
//${RTP_HAVE_SYS_FILIO}
//${RTP_HAVE_SYS_SOCKIO}
//${RTP_ENDIAN}
//${RTP_SOCKLENTYPE_UINT}
//${RTP_HAVE_SOCKADDR_LEN}
//${RTP_SUPPORT_IPV4MULTICAST}
//${RTP_SUPPORT_THREAD}
//${RTP_SUPPORT_SDESPRIV}
//${RTP_SUPPORT_PROBATION}
//${RTP_SUPPORT_GETLOGINR}
#define RTP_SUPPORT_IPV6
//${RTP_SUPPORT_IPV6MULTICAST}
//${RTP_SUPPORT_IFADDRS}
#define RTP_SUPPORT_SENDAPP
//${RTP_SUPPORT_MEMORYMANAGEMENT}
#define RTP_SUPPORT_RTCPUNKNOWN
#define RTP_DISABLE_INTERRUPT
#endif // RTPCONFIG_UNIX_H

View File

@@ -0,0 +1,178 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpconfig.h"
#ifdef RTPDEBUG
#include "rtptypes.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct MemoryInfo
{
void *ptr;
size_t size;
int lineno;
char *filename;
MemoryInfo *next;
};
class MemoryTracker
{
public:
MemoryTracker() { firstblock = NULL; }
~MemoryTracker()
{
MemoryInfo *tmp;
int count = 0;
printf("Checking for memory leaks...\n");fflush(stdout);
while(firstblock)
{
count++;
printf("Unfreed block %p of %d bytes (file '%s', line %d)\n",firstblock->ptr,(int)firstblock->size,firstblock->filename,firstblock->lineno);;
tmp = firstblock->next;
free(firstblock->ptr);
if (firstblock->filename)
free(firstblock->filename);
free(firstblock);
firstblock = tmp;
}
if (count == 0)
printf("No memory leaks found\n");
else
printf("%d leaks found\n",count);
}
MemoryInfo *firstblock;
};
static MemoryTracker memtrack;
void *donew(size_t s,char filename[],int line)
{
void *p;
MemoryInfo *meminf;
p = malloc(s);
meminf = (MemoryInfo *)malloc(sizeof(MemoryInfo));
meminf->ptr = p;
meminf->size = s;
meminf->lineno = line;
meminf->filename = (char *)malloc(strlen(filename)+1);
strcpy(meminf->filename,filename);
meminf->next = memtrack.firstblock;
memtrack.firstblock = meminf;
return p;
}
void dodelete(void *p)
{
MemoryInfo *tmp,*tmpprev;
bool found;
tmpprev = NULL;
tmp = memtrack.firstblock;
found = false;
while (tmp != NULL && !found)
{
if (tmp->ptr == p)
found = true;
else
{
tmpprev = tmp;
tmp = tmp->next;
}
}
if (!found)
{
printf("Couldn't free block %p!\n",p);
fflush(stdout);
}
else
{
MemoryInfo *n;
fflush(stdout);
n = tmp->next;
free(tmp->ptr);
if (tmp->filename)
free(tmp->filename);
free(tmp);
if (tmpprev)
tmpprev->next = n;
else
memtrack.firstblock = n;
}
}
void *operator new(size_t s)
{
return donew(s,"UNKNOWN FILE",0);
}
void *operator new[](size_t s)
{
return donew(s,"UNKNOWN FILE",0);
}
void *operator new(size_t s,char filename[],int line)
{
return donew(s,filename,line);
}
void *operator new[](size_t s,char filename[],int line)
{
return donew(s,filename,line);
}
void operator delete(void *p)
{
dodelete(p);
}
void operator delete[](void *p)
{
dodelete(p);
}
#endif // RTPDEBUG

View File

@@ -0,0 +1,52 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPDEBUG_H
#define RTPDEBUG_H
#include "rtpconfig.h"
#ifdef RTPDEBUG
#include "rtptypes.h"
void *operator new(size_t s,char filename[],int line);
#if ! (defined(WIN32) || defined(_WIN32_WCE))
void *operator new[](size_t s,char filename[],int line);
#define new new (__FILE__,__LINE__)
#else
#define new new (__FILE__,__LINE__)
#endif // WIN32
#endif // RTPDEBUG
#endif // RTPDEBUG_H

View File

@@ -0,0 +1,86 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPDEFINES_H
#define RTPDEFINES_H
#define RTP_VERSION 2
#define RTP_MAXCSRCS 15
#define RTP_MINPACKETSIZE 600
#define RTP_DEFAULTPACKETSIZE 1400
#define RTP_PROBATIONCOUNT 2
#define RTP_MAXPRIVITEMS 256
#define RTP_SENDERTIMEOUTMULTIPLIER 2
#define RTP_BYETIMEOUTMULTIPLIER 1
#define RTP_MEMBERTIMEOUTMULTIPLIER 5
#define RTP_COLLISIONTIMEOUTMULTIPLIER 10
#define RTP_NOTETTIMEOUTMULTIPLIER 25
#define RTP_DEFAULTSESSIONBANDWIDTH 10000.0
#define RTP_RTCPTYPE_SR 200
#define RTP_RTCPTYPE_RR 201
#define RTP_RTCPTYPE_SDES 202
#define RTP_RTCPTYPE_BYE 203
#define RTP_RTCPTYPE_APP 204
#define RTCP_SDES_ID_CNAME 1
#define RTCP_SDES_ID_NAME 2
#define RTCP_SDES_ID_EMAIL 3
#define RTCP_SDES_ID_PHONE 4
#define RTCP_SDES_ID_LOCATION 5
#define RTCP_SDES_ID_TOOL 6
#define RTCP_SDES_ID_NOTE 7
#define RTCP_SDES_ID_PRIVATE 8
#define RTCP_SDES_NUMITEMS_NONPRIVATE 7
#define RTCP_SDES_MAXITEMLENGTH 255
#define RTCP_BYE_MAXREASONLENGTH 255
#define RTCP_DEFAULTMININTERVAL 5.0
#define RTCP_DEFAULTBANDWIDTHFRACTION 0.05
#define RTCP_DEFAULTSENDERFRACTION 0.25
#define RTCP_DEFAULTHALFATSTARTUP true
#define RTCP_DEFAULTIMMEDIATEBYE true
#define RTCP_DEFAULTSRBYE true
#if (defined(WIN32) || defined(_WIN32_WCE))
#if (!defined(_WIN32_WCE)) && (defined(_MSC_VER) && _MSC_VER >= 1400 )
#define RTP_SNPRINTF _snprintf_s
#else
#define RTP_SNPRINTF _snprintf
#endif
#else
#define RTP_SNPRINTF snprintf
#endif // WIN32 || _WIN32_WCE
#endif // RTPDEFINES_H

View File

@@ -0,0 +1,257 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtperrors.h"
#include "rtpdefines.h"
#include <stdio.h>
#include "rtpdebug.h"
namespace jrtplib
{
struct RTPErrorInfo
{
int code;
const char *description;
};
static RTPErrorInfo ErrorDescriptions[]=
{
{ ERR_RTP_OUTOFMEM,"Out of memory" },
{ ERR_RTP_NOTHREADSUPPORT, "No JThread support was compiled in"},
{ ERR_RTP_COLLISIONLIST_BADADDRESS, "Passed invalid address (null) to collision list"},
{ ERR_RTP_HASHTABLE_ELEMENTALREADYEXISTS, "Element already exists in hash table"},
{ ERR_RTP_HASHTABLE_ELEMENTNOTFOUND, "Element not found in hash table"},
{ ERR_RTP_HASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX, "Function returned an illegal hash index"},
{ ERR_RTP_HASHTABLE_NOCURRENTELEMENT, "No current element selected in hash table"},
{ ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX, "Function returned an illegal hash index"},
{ ERR_RTP_KEYHASHTABLE_KEYALREADYEXISTS, "Key value already exists in key hash table"},
{ ERR_RTP_KEYHASHTABLE_KEYNOTFOUND, "Key value not found in key hash table"},
{ ERR_RTP_KEYHASHTABLE_NOCURRENTELEMENT, "No current element selected in key hash table"},
{ ERR_RTP_PACKBUILD_ALREADYINIT, "RTP packet builder is already initialized"},
{ ERR_RTP_PACKBUILD_CSRCALREADYINLIST, "The specified CSRC is already in the RTP packet builder's CSRC list"},
{ ERR_RTP_PACKBUILD_CSRCLISTFULL, "The RTP packet builder's CSRC list already contains 15 entries"},
{ ERR_RTP_PACKBUILD_CSRCNOTINLIST, "The specified CSRC was not found in the RTP packet builder's CSRC list"},
{ ERR_RTP_PACKBUILD_DEFAULTMARKNOTSET, "The RTP packet builder's default mark flag is not set"},
{ ERR_RTP_PACKBUILD_DEFAULTPAYLOADTYPENOTSET, "The RTP packet builder's default payload type is not set"},
{ ERR_RTP_PACKBUILD_DEFAULTTSINCNOTSET, "The RTP packet builder's default timestamp increment is not set"},
{ ERR_RTP_PACKBUILD_INVALIDMAXPACKETSIZE, "The specified maximum packet size for the RTP packet builder is invalid"},
{ ERR_RTP_PACKBUILD_NOTINIT, "The RTP packet builder is not initialized"},
{ ERR_RTP_PACKET_BADPAYLOADTYPE, "Invalid payload type"},
{ ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE, "Tried to create an RTP packet which whould exceed the specified maximum packet size"},
{ ERR_RTP_PACKET_EXTERNALBUFFERNULL, "Illegal value (null) passed as external buffer for the RTP packet"},
{ ERR_RTP_PACKET_ILLEGALBUFFERSIZE, "Illegal buffer size specified for the RTP packet"},
{ ERR_RTP_PACKET_INVALIDPACKET, "Invalid RTP packet format"},
{ ERR_RTP_PACKET_TOOMANYCSRCS, "More than 15 CSRCs specified for the RTP packet"},
{ ERR_RTP_POLLTHREAD_ALREADYRUNNING, "Poll thread is already running"},
{ ERR_RTP_POLLTHREAD_CANTINITMUTEX, "Can't initialize a mutex for the poll thread"},
{ ERR_RTP_POLLTHREAD_CANTSTARTTHREAD, "Can't start the poll thread"},
{ ERR_RTP_RTCPCOMPOUND_INVALIDPACKET, "Invalid RTCP compound packet format"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILDING, "Already building this RTCP compound packet"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILT, "This RTCP compound packet is already built"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYGOTREPORT, "There's already a SR or RR in this RTCP compound packet"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_APPDATALENTOOBIG, "The specified APP data length for the RTCP compound packet is too big"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_BUFFERSIZETOOSMALL, "The specified buffer size for the RTCP comound packet is too small"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALAPPDATALENGTH, "The APP data length must be a multiple of four"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALSUBTYPE, "The APP packet subtype must be smaller than 32"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_INVALIDITEMTYPE, "Invalid SDES item type specified for the RTCP compound packet"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_MAXPACKETSIZETOOSMALL, "The specified maximum packet size for the RTCP compound packet is too small"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE, "Tried to add an SDES item to the RTCP compound packet when no SSRC was present"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_NOREPORTPRESENT, "An RTCP compound packet must contain a SR or RR"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING, "The RTCP compound packet builder is not initialized"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT, "Adding this data would exceed the specified maximum RTCP compound packet size"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_REPORTNOTSTARTED, "Tried to add a report block to the RTCP compound packet when no SR or RR was started"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_TOOMANYSSRCS, "Only 31 SSRCs will fit into a BYE packet for the RTCP compound packet"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_TOTALITEMLENGTHTOOBIG, "The total data for the SDES PRIV item exceeds the maximum size (255 bytes) of an SDES item"},
{ ERR_RTP_RTCPPACKETBUILDER_ALREADYINIT, "The RTCP packet builder is already initialized"},
{ ERR_RTP_RTCPPACKETBUILDER_ILLEGALMAXPACKSIZE, "The specified maximum packet size for the RTCP packet builder is too small"},
{ ERR_RTP_RTCPPACKETBUILDER_ILLEGALTIMESTAMPUNIT, "Speficied an illegal timestamp unit for the the RTCP packet builder"},
{ ERR_RTP_RTCPPACKETBUILDER_NOTINIT, "The RTCP packet builder was not initialized"},
{ ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON, "The RTCP compound packet filled sooner than expected"},
{ ERR_RTP_SCHEDPARAMS_BADFRACTION, "Illegal sender bandwidth fraction specified"},
{ ERR_RTP_SCHEDPARAMS_BADMINIMUMINTERVAL, "The minimum RTCP interval specified for the scheduler is too small"},
{ ERR_RTP_SCHEDPARAMS_INVALIDBANDWIDTH, "Invalid RTCP bandwidth specified for the RTCP scheduler"},
{ ERR_RTP_SDES_LENGTHTOOBIG, "Specified size for the SDES item exceeds 255 bytes"},
{ ERR_RTP_SDES_PREFIXNOTFOUND, "The specified SDES PRIV prefix was not found"},
{ ERR_RTP_SESSION_ALREADYCREATED, "The session is already created"},
{ ERR_RTP_SESSION_CANTGETLOGINNAME, "Can't retrieve login name"},
{ ERR_RTP_SESSION_CANTINITMUTEX, "A mutex for the RTP session couldn't be initialized"},
{ ERR_RTP_SESSION_MAXPACKETSIZETOOSMALL, "The maximum packet size specified for the RTP session is too small"},
{ ERR_RTP_SESSION_NOTCREATED, "The RTP session was not created"},
{ ERR_RTP_SESSION_UNSUPPORTEDTRANSMISSIONPROTOCOL, "The requested transmission protocol for the RTP session is not supported"},
{ ERR_RTP_SESSION_USINGPOLLTHREAD, "This function is not available when using the RTP poll thread feature"},
{ ERR_RTP_SESSION_USERDEFINEDTRANSMITTERNULL, "A user-defined transmitter was requested but the supplied transmitter component is NULL"},
{ ERR_RTP_SOURCES_ALREADYHAVEOWNSSRC, "Only one source can be marked as own SSRC in the source table"},
{ ERR_RTP_SOURCES_DONTHAVEOWNSSRC, "No source was marked as own SSRC in the source table"},
{ ERR_RTP_SOURCES_ILLEGALSDESTYPE, "Illegal SDES type specified for processing into the source table"},
{ ERR_RTP_SOURCES_SSRCEXISTS, "Can't create own SSRC because this SSRC identifier is already in the source table"},
{ ERR_RTP_UDPV4TRANS_ALREADYCREATED, "The transmitter was already created"},
{ ERR_RTP_UDPV4TRANS_ALREADYINIT, "The transmitter was already initialize"},
{ ERR_RTP_UDPV4TRANS_ALREADYWAITING, "The transmitter is already waiting for incoming data"},
{ ERR_RTP_UDPV4TRANS_CANTBINDRTCPSOCKET, "The 'bind' call for the RTCP socket failed"},
{ ERR_RTP_UDPV4TRANS_CANTBINDRTPSOCKET, "The 'bind' call for the RTP socket failed"},
{ ERR_RTP_UDPV4TRANS_CANTCALCULATELOCALIP, "The local IP addresses could not be determined"},
{ ERR_RTP_UDPV4TRANS_CANTCREATEABORTDESCRIPTORS, "Couldn't create the sockets used to abort waiting for incoming data"},
{ ERR_RTP_UDPV4TRANS_CANTCREATEPIPE, "Couldn't create the pipe used to abort waiting for incoming data"},
{ ERR_RTP_UDPV4TRANS_CANTCREATESOCKET, "Couldn't create the RTP or RTCP socket"},
{ ERR_RTP_UDPV4TRANS_CANTINITMUTEX, "Failed to initialize a mutex used by the transmitter"},
{ ERR_RTP_UDPV4TRANS_CANTSETRTCPRECEIVEBUF, "Couldn't set the receive buffer size for the RTCP socket"},
{ ERR_RTP_UDPV4TRANS_CANTSETRTCPTRANSMITBUF, "Couldn't set the transmission buffer size for the RTCP socket"},
{ ERR_RTP_UDPV4TRANS_CANTSETRTPRECEIVEBUF, "Couldn't set the receive buffer size for the RTP socket"},
{ ERR_RTP_UDPV4TRANS_CANTSETRTPTRANSMITBUF, "Couldn't set the transmission buffer size for the RTP socket"},
{ ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP, "Unable to join the specified multicast group"},
{ ERR_RTP_UDPV4TRANS_DIFFERENTRECEIVEMODE, "The function called doens't match the current receive mode"},
{ ERR_RTP_UDPV4TRANS_ERRORINSELECT, "Error in the transmitter's 'select' call"},
{ ERR_RTP_UDPV4TRANS_ILLEGALPARAMETERS, "Illegal parameters type passed to the transmitter"},
{ ERR_RTP_UDPV4TRANS_INVALIDADDRESSTYPE, "Specified address type isn't compatible with this transmitter"},
{ ERR_RTP_UDPV4TRANS_NOLOCALIPS, "Couldn't determine the local host name since the local IP list is empty"},
{ ERR_RTP_UDPV4TRANS_NOMULTICASTSUPPORT, "Multicast support is not available"},
{ ERR_RTP_UDPV4TRANS_NOSUCHENTRY, "Specified entry could not be found"},
{ ERR_RTP_UDPV4TRANS_NOTAMULTICASTADDRESS, "The specified address is not a multicast address"},
{ ERR_RTP_UDPV4TRANS_NOTCREATED, "The 'Create' call for this transmitter has not been called"},
{ ERR_RTP_UDPV4TRANS_NOTINIT, "The 'Init' call for this transmitter has not been called"},
{ ERR_RTP_UDPV4TRANS_NOTWAITING, "The transmitter is not waiting for incoming data"},
{ ERR_RTP_UDPV4TRANS_PORTBASENOTEVEN, "The specified port base is not an even number"},
{ ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG, "The maximum packet size is too big for this transmitter"},
{ ERR_RTP_UDPV6TRANS_ALREADYCREATED, "The transmitter was already created"},
{ ERR_RTP_UDPV6TRANS_ALREADYINIT, "The transmitter was already initialize"},
{ ERR_RTP_UDPV6TRANS_ALREADYWAITING, "The transmitter is already waiting for incoming data"},
{ ERR_RTP_UDPV6TRANS_CANTBINDRTCPSOCKET, "The 'bind' call for the RTCP socket failed"},
{ ERR_RTP_UDPV6TRANS_CANTBINDRTPSOCKET, "The 'bind' call for the RTP socket failed"},
{ ERR_RTP_UDPV6TRANS_CANTCALCULATELOCALIP, "The local IP addresses could not be determined"},
{ ERR_RTP_UDPV6TRANS_CANTCREATEABORTDESCRIPTORS, "Couldn't create the sockets used to abort waiting for incoming data"},
{ ERR_RTP_UDPV6TRANS_CANTCREATEPIPE, "Couldn't create the pipe used to abort waiting for incoming data"},
{ ERR_RTP_UDPV6TRANS_CANTCREATESOCKET, "Couldn't create the RTP or RTCP socket"},
{ ERR_RTP_UDPV6TRANS_CANTINITMUTEX, "Failed to initialize a mutex used by the transmitter"},
{ ERR_RTP_UDPV6TRANS_CANTSETRTCPRECEIVEBUF, "Couldn't set the receive buffer size for the RTCP socket"},
{ ERR_RTP_UDPV6TRANS_CANTSETRTCPTRANSMITBUF, "Couldn't set the transmission buffer size for the RTCP socket"},
{ ERR_RTP_UDPV6TRANS_CANTSETRTPRECEIVEBUF, "Couldn't set the receive buffer size for the RTP socket"},
{ ERR_RTP_UDPV6TRANS_CANTSETRTPTRANSMITBUF, "Couldn't set the transmission buffer size for the RTP socket"},
{ ERR_RTP_UDPV6TRANS_COULDNTJOINMULTICASTGROUP, "Unable to join the specified multicast group"},
{ ERR_RTP_UDPV6TRANS_DIFFERENTRECEIVEMODE, "The function called doens't match the current receive mode"},
{ ERR_RTP_UDPV6TRANS_ERRORINSELECT, "Error in the transmitter's 'select' call"},
{ ERR_RTP_UDPV6TRANS_ILLEGALPARAMETERS, "Illegal parameters type passed to the transmitter"},
{ ERR_RTP_UDPV6TRANS_INVALIDADDRESSTYPE, "Specified address type isn't compatible with this transmitter"},
{ ERR_RTP_UDPV6TRANS_NOLOCALIPS, "Couldn't determine the local host name since the local IP list is empty"},
{ ERR_RTP_UDPV6TRANS_NOMULTICASTSUPPORT, "Multicast support is not available"},
{ ERR_RTP_UDPV6TRANS_NOSUCHENTRY, "Specified entry could not be found"},
{ ERR_RTP_UDPV6TRANS_NOTAMULTICASTADDRESS, "The specified address is not a multicast address"},
{ ERR_RTP_UDPV6TRANS_NOTCREATED, "The 'Create' call for this transmitter has not been called"},
{ ERR_RTP_UDPV6TRANS_NOTINIT, "The 'Init' call for this transmitter has not been called"},
{ ERR_RTP_UDPV6TRANS_NOTWAITING, "The transmitter is not waiting for incoming data"},
{ ERR_RTP_UDPV6TRANS_PORTBASENOTEVEN, "The specified port base is not an even number"},
{ ERR_RTP_UDPV6TRANS_SPECIFIEDSIZETOOBIG, "The maximum packet size is too big for this transmitter"},
{ ERR_RTP_TRANS_BUFFERLENGTHTOOSMALL,"The hostname is larger than the specified buffer size"},
{ ERR_RTP_SDES_MAXPRIVITEMS,"The maximum number of SDES private item prefixes was reached"},
{ ERR_RTP_INTERNALSOURCEDATA_INVALIDPROBATIONTYPE,"An invalid probation type was specified"},
{ ERR_RTP_FAKETRANS_ALREADYCREATED, "The transmitter was already created"},
{ ERR_RTP_FAKETRANS_ALREADYINIT, "The transmitter was already initialize"},
{ ERR_RTP_FAKETRANS_ALREADYWAITING, "The transmitter is already waiting for incoming data"},
{ ERR_RTP_FAKETRANS_CANTBINDRTCPSOCKET, "The 'bind' call for the RTCP socket failed"},
{ ERR_RTP_FAKETRANS_CANTBINDRTPSOCKET, "The 'bind' call for the RTP socket failed"},
{ ERR_RTP_FAKETRANS_CANTCALCULATELOCALIP, "The local IP addresses could not be determined"},
{ ERR_RTP_FAKETRANS_CANTCREATEABORTDESCRIPTORS, "Couldn't create the sockets used to abort waiting for incoming data"},
{ ERR_RTP_FAKETRANS_CANTCREATEPIPE, "Couldn't create the pipe used to abort waiting for incoming data"},
{ ERR_RTP_FAKETRANS_CANTCREATESOCKET, "Couldn't create the RTP or RTCP socket"},
{ ERR_RTP_FAKETRANS_CANTINITMUTEX, "Failed to initialize a mutex used by the transmitter"},
{ ERR_RTP_FAKETRANS_CANTSETRTCPRECEIVEBUF, "Couldn't set the receive buffer size for the RTCP socket"},
{ ERR_RTP_FAKETRANS_CANTSETRTCPTRANSMITBUF, "Couldn't set the transmission buffer size for the RTCP socket"},
{ ERR_RTP_FAKETRANS_CANTSETRTPRECEIVEBUF, "Couldn't set the receive buffer size for the RTP socket"},
{ ERR_RTP_FAKETRANS_CANTSETRTPTRANSMITBUF, "Couldn't set the transmission buffer size for the RTP socket"},
{ ERR_RTP_FAKETRANS_COULDNTJOINMULTICASTGROUP, "Unable to join the specified multicast group"},
{ ERR_RTP_FAKETRANS_DIFFERENTRECEIVEMODE, "The function called doens't match the current receive mode"},
{ ERR_RTP_FAKETRANS_ERRORINSELECT, "Error in the transmitter's 'select' call"},
{ ERR_RTP_FAKETRANS_ILLEGALPARAMETERS, "Illegal parameters type passed to the transmitter"},
{ ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE, "Specified address type isn't compatible with this transmitter"},
{ ERR_RTP_FAKETRANS_NOLOCALIPS, "Couldn't determine the local host name since the local IP list is empty"},
{ ERR_RTP_FAKETRANS_NOMULTICASTSUPPORT, "Multicast support is not available"},
{ ERR_RTP_FAKETRANS_NOSUCHENTRY, "Specified entry could not be found"},
{ ERR_RTP_FAKETRANS_NOTAMULTICASTADDRESS, "The specified address is not a multicast address"},
{ ERR_RTP_FAKETRANS_NOTCREATED, "The 'Create' call for this transmitter has not been called"},
{ ERR_RTP_FAKETRANS_NOTINIT, "The 'Init' call for this transmitter has not been called"},
{ ERR_RTP_FAKETRANS_NOTWAITING, "The transmitter is not waiting for incoming data"},
{ ERR_RTP_FAKETRANS_PORTBASENOTEVEN, "The specified port base is not an even number"},
{ ERR_RTP_FAKETRANS_SPECIFIEDSIZETOOBIG, "The maximum packet size is too big for this transmitter"},
{ ERR_RTP_FAKETRANS_INVALIDEVENT, "Expecting UNKNOWN_EVENT to set source address but got another type of event"},
{ ERR_RTP_FAKETRANS_SRCADDRNOTSET, "Got packet but src address information was not set, returning"},
{ ERR_RTP_FAKETRANS_NOTNETBUFFER, "Received buffer is not a GstNetBuffer"},
{ ERR_RTP_FAKETRANS_WAITNOTIMPLEMENTED, "The WaitForIncomingData is not implemented in the Gst transmitter"},
{ ERR_RTP_RTPRANDOMURANDOM_CANTOPEN, "Unable to open /dev/urandom for reading"},
{ ERR_RTP_RTPRANDOMURANDOM_ALREADYOPEN, "The device /dev/urandom was already opened"},
{ ERR_RTP_RTPRANDOMRANDS_NOTSUPPORTED, "The rand_s call is not supported on this platform"},
{ ERR_RTP_EXTERNALTRANS_ALREADYCREATED, "The external transmission component was already created"},
{ ERR_RTP_EXTERNALTRANS_ALREADYINIT, "The external transmission component was already initialized"},
{ ERR_RTP_EXTERNALTRANS_ALREADYWAITING, "The external transmission component is already waiting for incoming data"},
{ ERR_RTP_EXTERNALTRANS_BADRECEIVEMODE, "The external transmission component only supports accepting all incoming packets"},
{ ERR_RTP_EXTERNALTRANS_CANTCREATEABORTDESCRIPTORS, "The external transmitter was unable to create it's internal abort descriptors"},
{ ERR_RTP_EXTERNALTRANS_CANTCREATEPIPE, "The external transmitter was unable to create a pipe"},
{ ERR_RTP_EXTERNALTRANS_CANTINITMUTEX, "The external transmitter was unable to initialize a required mutex"},
{ ERR_RTP_EXTERNALTRANS_ERRORINSELECT, "An error in the external transmitter's 'select' call occurred"},
{ ERR_RTP_EXTERNALTRANS_ILLEGALPARAMETERS, "Only parameters of type RTPExternalTransmissionParams can be passed to the external transmission component"},
{ ERR_RTP_EXTERNALTRANS_NOACCEPTLIST, "The external transmitter does not have an accept list"},
{ ERR_RTP_EXTERNALTRANS_NODESTINATIONSSUPPORTED, "The external transmitter does not have a destination list"},
{ ERR_RTP_EXTERNALTRANS_NOIGNORELIST, "The external transmitter does not have an ignore list"},
{ ERR_RTP_EXTERNALTRANS_NOMULTICASTSUPPORT, "The external transmitter does not support the multicast functions"},
{ ERR_RTP_EXTERNALTRANS_NOSENDER, "No sender has been set for this external transmitter"},
{ ERR_RTP_EXTERNALTRANS_NOTCREATED, "The external transmitter has not been created yet"},
{ ERR_RTP_EXTERNALTRANS_NOTINIT, "The external transmitter has not been initialized yet"},
{ ERR_RTP_EXTERNALTRANS_NOTWAITING, "The external transmitter is not currently waiting for incoming data"},
{ ERR_RTP_EXTERNALTRANS_SENDERROR, "The external transmitter was unable to actually send the data"},
{ ERR_RTP_EXTERNALTRANS_SPECIFIEDSIZETOOBIG, "The specified data size exceeds the maximum amount that has been set"},
{ 0,0 }
};
std::string RTPGetErrorString(int errcode)
{
int i;
if (errcode >= 0)
return std::string("No error");
i = 0;
while (ErrorDescriptions[i].code != 0)
{
if (ErrorDescriptions[i].code == errcode)
return std::string(ErrorDescriptions[i].description);
i++;
}
char str[16];
RTP_SNPRINTF(str,16,"(%d)",errcode);
return std::string("Unknown error code") + std::string(str);
}
} // end namespace

View File

@@ -0,0 +1,236 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtperrors.h
*/
#ifndef RTPERRORS_H
#define RTPERRORS_H
#include "rtpconfig.h"
#include <string>
namespace jrtplib
{
/** Returns a string describing the error code \c errcode. */
std::string JRTPLIB_IMPORTEXPORT RTPGetErrorString(int errcode);
} // end namespace
#define ERR_RTP_OUTOFMEM -1
#define ERR_RTP_NOTHREADSUPPORT -2
#define ERR_RTP_COLLISIONLIST_BADADDRESS -3
#define ERR_RTP_HASHTABLE_ELEMENTALREADYEXISTS -4
#define ERR_RTP_HASHTABLE_ELEMENTNOTFOUND -5
#define ERR_RTP_HASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX -6
#define ERR_RTP_HASHTABLE_NOCURRENTELEMENT -7
#define ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX -8
#define ERR_RTP_KEYHASHTABLE_KEYALREADYEXISTS -9
#define ERR_RTP_KEYHASHTABLE_KEYNOTFOUND -10
#define ERR_RTP_KEYHASHTABLE_NOCURRENTELEMENT -11
#define ERR_RTP_PACKBUILD_ALREADYINIT -12
#define ERR_RTP_PACKBUILD_CSRCALREADYINLIST -13
#define ERR_RTP_PACKBUILD_CSRCLISTFULL -14
#define ERR_RTP_PACKBUILD_CSRCNOTINLIST -15
#define ERR_RTP_PACKBUILD_DEFAULTMARKNOTSET -16
#define ERR_RTP_PACKBUILD_DEFAULTPAYLOADTYPENOTSET -17
#define ERR_RTP_PACKBUILD_DEFAULTTSINCNOTSET -18
#define ERR_RTP_PACKBUILD_INVALIDMAXPACKETSIZE -19
#define ERR_RTP_PACKBUILD_NOTINIT -20
#define ERR_RTP_PACKET_BADPAYLOADTYPE -21
#define ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE -22
#define ERR_RTP_PACKET_EXTERNALBUFFERNULL -23
#define ERR_RTP_PACKET_ILLEGALBUFFERSIZE -24
#define ERR_RTP_PACKET_INVALIDPACKET -25
#define ERR_RTP_PACKET_TOOMANYCSRCS -26
#define ERR_RTP_POLLTHREAD_ALREADYRUNNING -27
#define ERR_RTP_POLLTHREAD_CANTINITMUTEX -28
#define ERR_RTP_POLLTHREAD_CANTSTARTTHREAD -29
#define ERR_RTP_RTCPCOMPOUND_INVALIDPACKET -30
#define ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILDING -31
#define ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILT -32
#define ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYGOTREPORT -33
#define ERR_RTP_RTCPCOMPPACKBUILDER_APPDATALENTOOBIG -34
#define ERR_RTP_RTCPCOMPPACKBUILDER_BUFFERSIZETOOSMALL -35
#define ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALAPPDATALENGTH -36
#define ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALSUBTYPE -37
#define ERR_RTP_RTCPCOMPPACKBUILDER_INVALIDITEMTYPE -38
#define ERR_RTP_RTCPCOMPPACKBUILDER_MAXPACKETSIZETOOSMALL -39
#define ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE -40
#define ERR_RTP_RTCPCOMPPACKBUILDER_NOREPORTPRESENT -41
#define ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING -42
#define ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT -43
#define ERR_RTP_RTCPCOMPPACKBUILDER_REPORTNOTSTARTED -44
#define ERR_RTP_RTCPCOMPPACKBUILDER_TOOMANYSSRCS -45
#define ERR_RTP_RTCPCOMPPACKBUILDER_TOTALITEMLENGTHTOOBIG -46
#define ERR_RTP_RTCPPACKETBUILDER_ALREADYINIT -47
#define ERR_RTP_RTCPPACKETBUILDER_ILLEGALMAXPACKSIZE -48
#define ERR_RTP_RTCPPACKETBUILDER_ILLEGALTIMESTAMPUNIT -49
#define ERR_RTP_RTCPPACKETBUILDER_NOTINIT -50
#define ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON -51
#define ERR_RTP_SCHEDPARAMS_BADFRACTION -52
#define ERR_RTP_SCHEDPARAMS_BADMINIMUMINTERVAL -53
#define ERR_RTP_SCHEDPARAMS_INVALIDBANDWIDTH -54
#define ERR_RTP_SDES_LENGTHTOOBIG -55
#define ERR_RTP_SDES_MAXPRIVITEMS -56
#define ERR_RTP_SDES_PREFIXNOTFOUND -57
#define ERR_RTP_SESSION_ALREADYCREATED -58
#define ERR_RTP_SESSION_CANTGETLOGINNAME -59
#define ERR_RTP_SESSION_CANTINITMUTEX -60
#define ERR_RTP_SESSION_MAXPACKETSIZETOOSMALL -61
#define ERR_RTP_SESSION_NOTCREATED -62
#define ERR_RTP_SESSION_UNSUPPORTEDTRANSMISSIONPROTOCOL -63
#define ERR_RTP_SESSION_USINGPOLLTHREAD -64
#define ERR_RTP_SOURCES_ALREADYHAVEOWNSSRC -65
#define ERR_RTP_SOURCES_DONTHAVEOWNSSRC -66
#define ERR_RTP_SOURCES_ILLEGALSDESTYPE -67
#define ERR_RTP_SOURCES_SSRCEXISTS -68
#define ERR_RTP_TRANS_BUFFERLENGTHTOOSMALL -69
#define ERR_RTP_UDPV4TRANS_ALREADYCREATED -70
#define ERR_RTP_UDPV4TRANS_ALREADYINIT -71
#define ERR_RTP_UDPV4TRANS_ALREADYWAITING -72
#define ERR_RTP_UDPV4TRANS_CANTBINDRTCPSOCKET -73
#define ERR_RTP_UDPV4TRANS_CANTBINDRTPSOCKET -74
#define ERR_RTP_UDPV4TRANS_CANTCALCULATELOCALIP -75
#define ERR_RTP_UDPV4TRANS_CANTCREATEABORTDESCRIPTORS -76
#define ERR_RTP_UDPV4TRANS_CANTCREATEPIPE -77
#define ERR_RTP_UDPV4TRANS_CANTCREATESOCKET -78
#define ERR_RTP_UDPV4TRANS_CANTINITMUTEX -79
#define ERR_RTP_UDPV4TRANS_CANTSETRTCPRECEIVEBUF -80
#define ERR_RTP_UDPV4TRANS_CANTSETRTCPTRANSMITBUF -81
#define ERR_RTP_UDPV4TRANS_CANTSETRTPRECEIVEBUF -82
#define ERR_RTP_UDPV4TRANS_CANTSETRTPTRANSMITBUF -83
#define ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP -84
#define ERR_RTP_UDPV4TRANS_DIFFERENTRECEIVEMODE -85
#define ERR_RTP_UDPV4TRANS_ERRORINSELECT -86
#define ERR_RTP_UDPV4TRANS_ILLEGALPARAMETERS -87
#define ERR_RTP_UDPV4TRANS_INVALIDADDRESSTYPE -88
#define ERR_RTP_UDPV4TRANS_NOLOCALIPS -89
#define ERR_RTP_UDPV4TRANS_NOMULTICASTSUPPORT -90
#define ERR_RTP_UDPV4TRANS_NOSUCHENTRY -91
#define ERR_RTP_UDPV4TRANS_NOTAMULTICASTADDRESS -92
#define ERR_RTP_UDPV4TRANS_NOTCREATED -93
#define ERR_RTP_UDPV4TRANS_NOTINIT -94
#define ERR_RTP_UDPV4TRANS_NOTWAITING -95
#define ERR_RTP_UDPV4TRANS_PORTBASENOTEVEN -96
#define ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG -97
#define ERR_RTP_UDPV6TRANS_ALREADYCREATED -98
#define ERR_RTP_UDPV6TRANS_ALREADYINIT -99
#define ERR_RTP_UDPV6TRANS_ALREADYWAITING -100
#define ERR_RTP_UDPV6TRANS_CANTBINDRTCPSOCKET -101
#define ERR_RTP_UDPV6TRANS_CANTBINDRTPSOCKET -102
#define ERR_RTP_UDPV6TRANS_CANTCALCULATELOCALIP -103
#define ERR_RTP_UDPV6TRANS_CANTCREATEABORTDESCRIPTORS -104
#define ERR_RTP_UDPV6TRANS_CANTCREATEPIPE -105
#define ERR_RTP_UDPV6TRANS_CANTCREATESOCKET -106
#define ERR_RTP_UDPV6TRANS_CANTINITMUTEX -107
#define ERR_RTP_UDPV6TRANS_CANTSETRTCPRECEIVEBUF -108
#define ERR_RTP_UDPV6TRANS_CANTSETRTCPTRANSMITBUF -109
#define ERR_RTP_UDPV6TRANS_CANTSETRTPRECEIVEBUF -110
#define ERR_RTP_UDPV6TRANS_CANTSETRTPTRANSMITBUF -111
#define ERR_RTP_UDPV6TRANS_COULDNTJOINMULTICASTGROUP -112
#define ERR_RTP_UDPV6TRANS_DIFFERENTRECEIVEMODE -113
#define ERR_RTP_UDPV6TRANS_ERRORINSELECT -114
#define ERR_RTP_UDPV6TRANS_ILLEGALPARAMETERS -115
#define ERR_RTP_UDPV6TRANS_INVALIDADDRESSTYPE -116
#define ERR_RTP_UDPV6TRANS_NOLOCALIPS -117
#define ERR_RTP_UDPV6TRANS_NOMULTICASTSUPPORT -118
#define ERR_RTP_UDPV6TRANS_NOSUCHENTRY -119
#define ERR_RTP_UDPV6TRANS_NOTAMULTICASTADDRESS -120
#define ERR_RTP_UDPV6TRANS_NOTCREATED -121
#define ERR_RTP_UDPV6TRANS_NOTINIT -122
#define ERR_RTP_UDPV6TRANS_NOTWAITING -123
#define ERR_RTP_UDPV6TRANS_PORTBASENOTEVEN -124
#define ERR_RTP_UDPV6TRANS_SPECIFIEDSIZETOOBIG -125
#define ERR_RTP_INTERNALSOURCEDATA_INVALIDPROBATIONTYPE -126
#define ERR_RTP_SESSION_USERDEFINEDTRANSMITTERNULL -127
#define ERR_RTP_FAKETRANS_ALREADYCREATED -128
#define ERR_RTP_FAKETRANS_ALREADYINIT -129
#define ERR_RTP_FAKETRANS_ALREADYWAITING -130
#define ERR_RTP_FAKETRANS_CANTBINDRTCPSOCKET -131
#define ERR_RTP_FAKETRANS_CANTBINDRTPSOCKET -132
#define ERR_RTP_FAKETRANS_CANTCALCULATELOCALIP -133
#define ERR_RTP_FAKETRANS_CANTCREATEABORTDESCRIPTORS -134
#define ERR_RTP_FAKETRANS_CANTCREATEPIPE -135
#define ERR_RTP_FAKETRANS_CANTCREATESOCKET -136
#define ERR_RTP_FAKETRANS_CANTINITMUTEX -137
#define ERR_RTP_FAKETRANS_CANTSETRTCPRECEIVEBUF -138
#define ERR_RTP_FAKETRANS_CANTSETRTCPTRANSMITBUF -139
#define ERR_RTP_FAKETRANS_CANTSETRTPRECEIVEBUF -140
#define ERR_RTP_FAKETRANS_CANTSETRTPTRANSMITBUF -141
#define ERR_RTP_FAKETRANS_COULDNTJOINMULTICASTGROUP -142
#define ERR_RTP_FAKETRANS_DIFFERENTRECEIVEMODE -143
#define ERR_RTP_FAKETRANS_ERRORINSELECT -144
#define ERR_RTP_FAKETRANS_ILLEGALPARAMETERS -145
#define ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE -146
#define ERR_RTP_FAKETRANS_NOLOCALIPS -147
#define ERR_RTP_FAKETRANS_NOMULTICASTSUPPORT -148
#define ERR_RTP_FAKETRANS_NOSUCHENTRY -149
#define ERR_RTP_FAKETRANS_NOTAMULTICASTADDRESS -150
#define ERR_RTP_FAKETRANS_NOTCREATED -151
#define ERR_RTP_FAKETRANS_NOTINIT -152
#define ERR_RTP_FAKETRANS_NOTWAITING -153
#define ERR_RTP_FAKETRANS_PORTBASENOTEVEN -154
#define ERR_RTP_FAKETRANS_SPECIFIEDSIZETOOBIG -155
#define ERR_RTP_FAKETRANS_INVALIDEVENT -156
#define ERR_RTP_FAKETRANS_SRCADDRNOTSET -157
#define ERR_RTP_FAKETRANS_NOTNETBUFFER -158
#define ERR_RTP_FAKETRANS_WAITNOTIMPLEMENTED -159
#define ERR_RTP_RTPRANDOMURANDOM_CANTOPEN -160
#define ERR_RTP_RTPRANDOMURANDOM_ALREADYOPEN -161
#define ERR_RTP_RTPRANDOMRANDS_NOTSUPPORTED -162
#define ERR_RTP_EXTERNALTRANS_ALREADYCREATED -163
#define ERR_RTP_EXTERNALTRANS_ALREADYINIT -164
#define ERR_RTP_EXTERNALTRANS_ALREADYWAITING -165
#define ERR_RTP_EXTERNALTRANS_BADRECEIVEMODE -166
#define ERR_RTP_EXTERNALTRANS_CANTCREATEABORTDESCRIPTORS -167
#define ERR_RTP_EXTERNALTRANS_CANTCREATEPIPE -168
#define ERR_RTP_EXTERNALTRANS_CANTINITMUTEX -169
#define ERR_RTP_EXTERNALTRANS_ERRORINSELECT -170
#define ERR_RTP_EXTERNALTRANS_ILLEGALPARAMETERS -171
#define ERR_RTP_EXTERNALTRANS_NOACCEPTLIST -172
#define ERR_RTP_EXTERNALTRANS_NODESTINATIONSSUPPORTED -173
#define ERR_RTP_EXTERNALTRANS_NOIGNORELIST -174
#define ERR_RTP_EXTERNALTRANS_NOMULTICASTSUPPORT -175
#define ERR_RTP_EXTERNALTRANS_NOSENDER -176
#define ERR_RTP_EXTERNALTRANS_NOTCREATED -177
#define ERR_RTP_EXTERNALTRANS_NOTINIT -178
#define ERR_RTP_EXTERNALTRANS_NOTWAITING -179
#define ERR_RTP_EXTERNALTRANS_SENDERROR -180
#define ERR_RTP_EXTERNALTRANS_SPECIFIEDSIZETOOBIG -181
#endif // RTPERRORS_H

View File

@@ -0,0 +1,929 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpexternaltransmitter.h"
#include "rtprawpacket.h"
#include "rtptimeutilities.h"
#include "rtpdefines.h"
#include "rtperrors.h"
#include <stdio.h>
#include <string.h>
#ifdef RTPDEBUG
#include <iostream>
#endif // RTPDEBUG
#include "rtpdebug.h"
#include <iostream>
#if (defined(WIN32) || defined(_WIN32_WCE))
#define RTPSOCKERR INVALID_SOCKET
#define RTPCLOSE(x) closesocket(x)
#define RTPSOCKLENTYPE int
#define RTPIOCTL ioctlsocket
#else // not Win32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#ifdef RTP_HAVE_SYS_FILIO
#include <sys/filio.h>
#endif // RTP_HAVE_SYS_FILIO
#ifdef RTP_HAVE_SYS_SOCKIO
#include <sys/sockio.h>
#endif // RTP_HAVE_SYS_SOCKIO
#ifdef RTP_SUPPORT_IFADDRS
#include <ifaddrs.h>
#endif // RTP_SUPPORT_IFADDRS
#define RTPSOCKERR -1
#define RTPCLOSE(x) close(x)
#ifdef RTP_SOCKLENTYPE_UINT
#define RTPSOCKLENTYPE unsigned int
#else
#define RTPSOCKLENTYPE int
#endif // RTP_SOCKLENTYPE_UINT
#define RTPIOCTL ioctl
#endif // WIN32
#ifdef RTP_SUPPORT_THREAD
#define MAINMUTEX_LOCK { if (threadsafe) mainmutex.Lock(); }
#define MAINMUTEX_UNLOCK { if (threadsafe) mainmutex.Unlock(); }
#define WAITMUTEX_LOCK { if (threadsafe) waitmutex.Lock(); }
#define WAITMUTEX_UNLOCK { if (threadsafe) waitmutex.Unlock(); }
#else
#define MAINMUTEX_LOCK
#define MAINMUTEX_UNLOCK
#define WAITMUTEX_LOCK
#define WAITMUTEX_UNLOCK
#endif // RTP_SUPPORT_THREAD
namespace jrtplib
{
RTPExternalTransmitter::RTPExternalTransmitter(RTPMemoryManager *mgr) : RTPTransmitter(mgr), packetinjector((RTPExternalTransmitter *)this)
{
created = false;
init = false;
#if (defined(WIN32) || defined(_WIN32_WCE))
timeinit.Dummy();
#endif // WIN32 || _WIN32_WCE
}
RTPExternalTransmitter::~RTPExternalTransmitter()
{
Destroy();
}
int RTPExternalTransmitter::Init(bool tsafe)
{
if (init)
return ERR_RTP_EXTERNALTRANS_ALREADYINIT;
#ifdef RTP_SUPPORT_THREAD
threadsafe = tsafe;
if (threadsafe)
{
int status;
status = mainmutex.Init();
if (status < 0)
return ERR_RTP_EXTERNALTRANS_CANTINITMUTEX;
status = waitmutex.Init();
if (status < 0)
return ERR_RTP_EXTERNALTRANS_CANTINITMUTEX;
}
#else
if (tsafe)
return ERR_RTP_NOTHREADSUPPORT;
#endif // RTP_SUPPORT_THREAD
init = true;
return 0;
}
int RTPExternalTransmitter::Create(size_t maximumpacketsize,const RTPTransmissionParams *transparams)
{
const RTPExternalTransmissionParams *params;
int status;
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_ALREADYCREATED;
}
// Obtain transmission parameters
if (transparams == 0)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_ILLEGALPARAMETERS;
}
if (transparams->GetTransmissionProtocol() != RTPTransmitter::ExternalProto)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_ILLEGALPARAMETERS;
}
params = (const RTPExternalTransmissionParams *)transparams;
if ((status = CreateAbortDescriptors()) < 0)
{
MAINMUTEX_UNLOCK
return status;
}
maxpacksize = maximumpacketsize;
sender = params->GetSender();
headersize = params->GetAdditionalHeaderSize();
localhostname = 0;
localhostnamelength = 0;
waitingfordata = false;
created = true;
MAINMUTEX_UNLOCK
return 0;
}
void RTPExternalTransmitter::Destroy()
{
if (!init)
return;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK;
return;
}
if (localhostname)
{
RTPDeleteByteArray(localhostname,GetMemoryManager());
localhostname = 0;
localhostnamelength = 0;
}
FlushPackets();
created = false;
if (waitingfordata)
{
AbortWaitInternal();
DestroyAbortDescriptors();
MAINMUTEX_UNLOCK
WAITMUTEX_LOCK // to make sure that the WaitForIncomingData function ended
WAITMUTEX_UNLOCK
}
else
DestroyAbortDescriptors();
MAINMUTEX_UNLOCK
}
RTPTransmissionInfo *RTPExternalTransmitter::GetTransmissionInfo()
{
if (!init)
return 0;
MAINMUTEX_LOCK
RTPTransmissionInfo *tinf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPTRANSMISSIONINFO) RTPExternalTransmissionInfo(&packetinjector);
MAINMUTEX_UNLOCK
return tinf;
}
void RTPExternalTransmitter::DeleteTransmissionInfo(RTPTransmissionInfo *i)
{
if (!init)
return;
RTPDelete(i, GetMemoryManager());
}
int RTPExternalTransmitter::GetLocalHostName(uint8_t *buffer,size_t *bufferlength)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (localhostname == 0)
{
// We'll just use 'gethostname' for simplicity
char name[1024];
if (gethostname(name,1023) != 0)
strcpy(name, "localhost"); // failsafe
else
name[1023] = 0; // ensure null-termination
localhostnamelength = strlen(name);
localhostname = RTPNew(GetMemoryManager(),RTPMEM_TYPE_OTHER) uint8_t [localhostnamelength+1];
memcpy(localhostname, name, localhostnamelength);
localhostname[localhostnamelength] = 0;
}
if ((*bufferlength) < localhostnamelength)
{
*bufferlength = localhostnamelength; // tell the application the required size of the buffer
MAINMUTEX_UNLOCK
return ERR_RTP_TRANS_BUFFERLENGTHTOOSMALL;
}
memcpy(buffer,localhostname,localhostnamelength);
*bufferlength = localhostnamelength;
MAINMUTEX_UNLOCK
return 0;
}
bool RTPExternalTransmitter::ComesFromThisTransmitter(const RTPAddress *addr)
{
MAINMUTEX_LOCK
bool value = false;
if (sender)
value = sender->ComesFromThisSender(addr);
MAINMUTEX_UNLOCK
return value;
}
int RTPExternalTransmitter::Poll()
{
return 0;
}
int RTPExternalTransmitter::WaitForIncomingData(const RTPTime &delay,bool *dataavailable)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
fd_set fdset;
struct timeval tv;
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (waitingfordata)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_ALREADYWAITING;
}
FD_ZERO(&fdset);
FD_SET(abortdesc[0],&fdset);
tv.tv_sec = delay.GetSeconds();
tv.tv_usec = delay.GetMicroSeconds();
waitingfordata = true;
if (!rawpacketlist.empty())
{
if (dataavailable != 0)
*dataavailable = true;
waitingfordata = false;
MAINMUTEX_UNLOCK
return 0;
}
WAITMUTEX_LOCK
MAINMUTEX_UNLOCK
if (select(FD_SETSIZE,&fdset,0,0,&tv) < 0)
{
MAINMUTEX_LOCK
waitingfordata = false;
MAINMUTEX_UNLOCK
WAITMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_ERRORINSELECT;
}
MAINMUTEX_LOCK
waitingfordata = false;
if (!created) // destroy called
{
MAINMUTEX_UNLOCK;
WAITMUTEX_UNLOCK
return 0;
}
// if aborted, read from abort buffer
if (FD_ISSET(abortdesc[0],&fdset))
{
#define BUFLEN 256
#if (defined(WIN32) || defined(_WIN32_WCE))
char buf[BUFLEN];
unsigned long len, len2;
#else
size_t len, len2;
unsigned char buf[BUFLEN];
#endif // WIN32
len = 0;
RTPIOCTL(abortdesc[0],FIONREAD,&len);
while (len > 0)
{
len2 = len;
if (len2 > BUFLEN)
len2 = BUFLEN;
#if (defined(WIN32) || defined(_WIN32_WCE))
recv(abortdesc[0],buf,len2,0);
#else
if (read(abortdesc[0],buf,len2)) { } // To get rid of __wur related compiler warnings
#endif // WIN32
len -= len2;
}
}
if (dataavailable != 0)
{
if (rawpacketlist.empty())
*dataavailable = false;
else
*dataavailable = true;
}
MAINMUTEX_UNLOCK
WAITMUTEX_UNLOCK
return 0;
}
int RTPExternalTransmitter::AbortWait()
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (!waitingfordata)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTWAITING;
}
AbortWaitInternal();
MAINMUTEX_UNLOCK
return 0;
}
int RTPExternalTransmitter::SendRTPData(const void *data,size_t len)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (len > maxpacksize)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_SPECIFIEDSIZETOOBIG;
}
if (!sender)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOSENDER;
}
MAINMUTEX_UNLOCK
if (!sender->SendRTP(data, len))
return ERR_RTP_EXTERNALTRANS_SENDERROR;
return 0;
}
int RTPExternalTransmitter::SendRTCPData(const void *data,size_t len)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (len > maxpacksize)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_SPECIFIEDSIZETOOBIG;
}
if (!sender)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOSENDER;
}
MAINMUTEX_UNLOCK
if (!sender->SendRTCP(data, len))
return ERR_RTP_EXTERNALTRANS_SENDERROR;
return 0;
}
int RTPExternalTransmitter::AddDestination(const RTPAddress &addr)
{
return ERR_RTP_EXTERNALTRANS_NODESTINATIONSSUPPORTED;
}
int RTPExternalTransmitter::DeleteDestination(const RTPAddress &addr)
{
return ERR_RTP_EXTERNALTRANS_NODESTINATIONSSUPPORTED;
}
void RTPExternalTransmitter::ClearDestinations()
{
}
bool RTPExternalTransmitter::SupportsMulticasting()
{
return false;
}
int RTPExternalTransmitter::JoinMulticastGroup(const RTPAddress &addr)
{
return ERR_RTP_EXTERNALTRANS_NOMULTICASTSUPPORT;
}
int RTPExternalTransmitter::LeaveMulticastGroup(const RTPAddress &addr)
{
return ERR_RTP_EXTERNALTRANS_NOMULTICASTSUPPORT;
}
void RTPExternalTransmitter::LeaveAllMulticastGroups()
{
}
int RTPExternalTransmitter::SetReceiveMode(RTPTransmitter::ReceiveMode m)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (m != RTPTransmitter::AcceptAll)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_BADRECEIVEMODE;
}
MAINMUTEX_UNLOCK
return 0;
}
int RTPExternalTransmitter::AddToIgnoreList(const RTPAddress &addr)
{
return ERR_RTP_EXTERNALTRANS_NOIGNORELIST;
}
int RTPExternalTransmitter::DeleteFromIgnoreList(const RTPAddress &addr)
{
return ERR_RTP_EXTERNALTRANS_NOIGNORELIST;
}
void RTPExternalTransmitter::ClearIgnoreList()
{
}
int RTPExternalTransmitter::AddToAcceptList(const RTPAddress &addr)
{
return ERR_RTP_EXTERNALTRANS_NOACCEPTLIST;
}
int RTPExternalTransmitter::DeleteFromAcceptList(const RTPAddress &addr)
{
return ERR_RTP_EXTERNALTRANS_NOACCEPTLIST;
}
void RTPExternalTransmitter::ClearAcceptList()
{
}
int RTPExternalTransmitter::SetMaximumPacketSize(size_t s)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
maxpacksize = s;
MAINMUTEX_UNLOCK
return 0;
}
bool RTPExternalTransmitter::NewDataAvailable()
{
if (!init)
return false;
MAINMUTEX_LOCK
bool v;
if (!created)
v = false;
else
{
if (rawpacketlist.empty())
v = false;
else
v = true;
}
MAINMUTEX_UNLOCK
return v;
}
RTPRawPacket *RTPExternalTransmitter::GetNextPacket()
{
if (!init)
return 0;
MAINMUTEX_LOCK
RTPRawPacket *p;
if (!created)
{
MAINMUTEX_UNLOCK
return 0;
}
if (rawpacketlist.empty())
{
MAINMUTEX_UNLOCK
return 0;
}
p = *(rawpacketlist.begin());
rawpacketlist.pop_front();
MAINMUTEX_UNLOCK
return p;
}
// Here the private functions start...
void RTPExternalTransmitter::FlushPackets()
{
std::list<RTPRawPacket*>::const_iterator it;
for (it = rawpacketlist.begin() ; it != rawpacketlist.end() ; ++it)
RTPDelete(*it,GetMemoryManager());
rawpacketlist.clear();
}
#if (defined(WIN32) || defined(_WIN32_WCE))
int RTPExternalTransmitter::CreateAbortDescriptors()
{
SOCKET listensock;
int size;
struct sockaddr_in addr;
listensock = socket(PF_INET,SOCK_STREAM,0);
if (listensock == RTPSOCKERR)
return ERR_RTP_EXTERNALTRANS_CANTCREATEABORTDESCRIPTORS;
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
if (bind(listensock,(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) != 0)
{
RTPCLOSE(listensock);
return ERR_RTP_EXTERNALTRANS_CANTCREATEABORTDESCRIPTORS;
}
memset(&addr,0,sizeof(struct sockaddr_in));
size = sizeof(struct sockaddr_in);
if (getsockname(listensock,(struct sockaddr*)&addr,&size) != 0)
{
RTPCLOSE(listensock);
return ERR_RTP_EXTERNALTRANS_CANTCREATEABORTDESCRIPTORS;
}
unsigned short connectport = ntohs(addr.sin_port);
abortdesc[0] = socket(PF_INET,SOCK_STREAM,0);
if (abortdesc[0] == RTPSOCKERR)
{
RTPCLOSE(listensock);
return ERR_RTP_EXTERNALTRANS_CANTCREATEABORTDESCRIPTORS;
}
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
if (bind(abortdesc[0],(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) != 0)
{
RTPCLOSE(listensock);
RTPCLOSE(abortdesc[0]);
return ERR_RTP_EXTERNALTRANS_CANTCREATEABORTDESCRIPTORS;
}
if (listen(listensock,1) != 0)
{
RTPCLOSE(listensock);
RTPCLOSE(abortdesc[0]);
return ERR_RTP_EXTERNALTRANS_CANTCREATEABORTDESCRIPTORS;
}
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(connectport);
if (connect(abortdesc[0],(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) != 0)
{
RTPCLOSE(listensock);
RTPCLOSE(abortdesc[0]);
return ERR_RTP_EXTERNALTRANS_CANTCREATEABORTDESCRIPTORS;
}
memset(&addr,0,sizeof(struct sockaddr_in));
size = sizeof(struct sockaddr_in);
abortdesc[1] = accept(listensock,(struct sockaddr *)&addr,&size);
if (abortdesc[1] == RTPSOCKERR)
{
RTPCLOSE(listensock);
RTPCLOSE(abortdesc[0]);
return ERR_RTP_EXTERNALTRANS_CANTCREATEABORTDESCRIPTORS;
}
// okay, got the connection, close the listening socket
RTPCLOSE(listensock);
return 0;
}
void RTPExternalTransmitter::DestroyAbortDescriptors()
{
RTPCLOSE(abortdesc[0]);
RTPCLOSE(abortdesc[1]);
}
#else // in a non winsock environment we can use pipes
int RTPExternalTransmitter::CreateAbortDescriptors()
{
#ifndef RTP_DISABLE_INTERRUPT
if (pipe(abortdesc) < 0)
return ERR_RTP_EXTERNALTRANS_CANTCREATEPIPE;
#endif
return 0;
}
void RTPExternalTransmitter::DestroyAbortDescriptors()
{
#ifndef RTP_DISABLE_INTERRUPT
close(abortdesc[0]);
close(abortdesc[1]);
#endif
}
#endif // WIN32
void RTPExternalTransmitter::AbortWaitInternal()
{
#if (defined(WIN32) || defined(_WIN32_WCE))
send(abortdesc[1],"*",1,0);
#else
//if (write(abortdesc[1],"*",1))
{
// To get rid of __wur related compiler warnings
}
#endif // WIN32
}
void RTPExternalTransmitter::InjectRTP(const void *data, size_t len, const RTPAddress &a)
{
if (!init)
return;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return;
}
RTPAddress *addr = a.CreateCopy(GetMemoryManager());
if (addr == 0)
return;
uint8_t *datacopy;
datacopy = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RECEIVEDRTPPACKET) uint8_t[len];
if (datacopy == 0)
{
RTPDelete(addr,GetMemoryManager());
return;
}
memcpy(datacopy, data, len);
RTPTime curtime = RTPTime::CurrentTime();
RTPRawPacket *pack;
pack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPRAWPACKET) RTPRawPacket(datacopy,len,addr,curtime,true,GetMemoryManager());
if (pack == 0)
{
RTPDelete(addr,GetMemoryManager());
RTPDeleteByteArray(localhostname,GetMemoryManager());
return;
}
rawpacketlist.push_back(pack);
AbortWaitInternal();
MAINMUTEX_UNLOCK
}
void RTPExternalTransmitter::InjectRTCP(const void *data, size_t len, const RTPAddress &a)
{
if (!init)
return;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return;
}
RTPAddress *addr = a.CreateCopy(GetMemoryManager());
if (addr == 0)
return;
uint8_t *datacopy;
datacopy = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RECEIVEDRTCPPACKET) uint8_t[len];
if (datacopy == 0)
{
RTPDelete(addr,GetMemoryManager());
return;
}
memcpy(datacopy, data, len);
RTPTime curtime = RTPTime::CurrentTime();
RTPRawPacket *pack;
pack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPRAWPACKET) RTPRawPacket(datacopy,len,addr,curtime,false,GetMemoryManager());
if (pack == 0)
{
RTPDelete(addr,GetMemoryManager());
RTPDeleteByteArray(localhostname,GetMemoryManager());
return;
}
rawpacketlist.push_back(pack);
AbortWaitInternal();
MAINMUTEX_UNLOCK
}
void RTPExternalTransmitter::InjectRTPorRTCP(const void *data, size_t len, const RTPAddress &a)
{
if (!init)
return;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return;
}
RTPAddress *addr = a.CreateCopy(GetMemoryManager());
if (addr == 0)
return;
uint8_t *datacopy;
bool rtp = true;
if (len >= 2)
{
const uint8_t *pData = (const uint8_t *)data;
if (pData[1] >= 200 && pData[1] <= 204)
rtp = false;
}
datacopy = RTPNew(GetMemoryManager(),(rtp)?RTPMEM_TYPE_BUFFER_RECEIVEDRTPPACKET:RTPMEM_TYPE_BUFFER_RECEIVEDRTCPPACKET) uint8_t[len];
if (datacopy == 0)
{
RTPDelete(addr,GetMemoryManager());
return;
}
memcpy(datacopy, data, len);
RTPTime curtime = RTPTime::CurrentTime();
RTPRawPacket *pack;
pack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPRAWPACKET) RTPRawPacket(datacopy,len,addr,curtime,rtp,GetMemoryManager());
if (pack == 0)
{
RTPDelete(addr,GetMemoryManager());
RTPDeleteByteArray(localhostname,GetMemoryManager());
return;
}
rawpacketlist.push_back(pack);
AbortWaitInternal();
MAINMUTEX_UNLOCK
}
#ifdef RTPDEBUG
void RTPExternalTransmitter::Dump()
{
if (!init)
std::cout << "Not initialized" << std::endl;
else
{
MAINMUTEX_LOCK
if (!created)
std::cout << "Not created" << std::endl;
else
{
std::cout << "Number of raw packets in queue: " << rawpacketlist.size() << std::endl;
std::cout << "Maximum allowed packet size: " << maxpacksize << std::endl;
}
MAINMUTEX_UNLOCK
}
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,240 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpexternaltransmitter.h
*/
#ifndef RTPEXTERNALTRANSMITTER_H
#define RTPEXTERNALTRANSMITTER_H
#include "rtpconfig.h"
#include "rtptransmitter.h"
#include <list>
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jmutex.h>
#endif // RTP_SUPPORT_THREAD
namespace jrtplib
{
class RTPExternalTransmitter;
/** Base class to specify a mechanism to transmit RTP packets outside of this library.
* Base class to specify a mechanism to transmit RTP packets outside of this library. When
* you want to use your own mechanism to transmit RTP packets, you need to specify that
* you'll be using the external transmission component, and derive a class from this base
* class. An instance should then be specified in the RTPExternalTransmissionParams object,
* so that the transmitter will call the \c SendRTP, \c SendRTCP and \c ComesFromThisSender
* methods of this instance when needed.
*/
class JRTPLIB_IMPORTEXPORT RTPExternalSender
{
public:
RTPExternalSender() { }
virtual ~RTPExternalSender() { }
/** This member function will be called when RTP data needs to be transmitted. */
virtual bool SendRTP(const void *data, size_t len) = 0;
/** This member function will be called when an RTCP packet needs to be transmitted. */
virtual bool SendRTCP(const void *data, size_t len) = 0;
/** Used to identify if an RTPAddress instance originated from this sender (to be able to detect own packets). */
virtual bool ComesFromThisSender(const RTPAddress *a) = 0;
};
/** Interface to inject incoming RTP and RTCP packets into the library.
* Interface to inject incoming RTP and RTCP packets into the library. When you have your own
* mechanism to receive incoming RTP/RTCP data, you'll need to pass these packets to the library.
* By first retrieving the RTPExternalTransmissionInfo instance for the external transmitter you'll
* be using, you can obtain the associated RTPExternalPacketInjecter instance. By calling it's
* member functions, you can then inject RTP or RTCP data into the library for further processing.
*/
class JRTPLIB_IMPORTEXPORT RTPExternalPacketInjecter
{
public:
RTPExternalPacketInjecter(RTPExternalTransmitter *trans) { transmitter = trans; }
~RTPExternalPacketInjecter() { }
/** This function can be called to insert an RTP packet into the transmission component. */
void InjectRTP(const void *data, size_t len, const RTPAddress &a);
/** This function can be called to insert an RTCP packet into the transmission component. */
void InjectRTCP(const void *data, size_t len, const RTPAddress &a);
/** Use this function to inject an RTP or RTCP packet and the transmitter will try to figure out which type of packet it is. */
void InjectRTPorRTCP(const void *data, size_t len, const RTPAddress &a);
private:
RTPExternalTransmitter *transmitter;
};
/** Parameters to initialize a transmitter of type RTPExternalTransmitter. */
class JRTPLIB_IMPORTEXPORT RTPExternalTransmissionParams : public RTPTransmissionParams
{
public:
/** Using this constructor you can specify which RTPExternalSender object you'll be using
* and how much the additional header overhead for each packet will be. */
RTPExternalTransmissionParams(RTPExternalSender *s, int headeroverhead):RTPTransmissionParams(RTPTransmitter::ExternalProto) { sender = s; headersize = headeroverhead; }
RTPExternalSender *GetSender() const { return sender; }
int GetAdditionalHeaderSize() const { return headersize; }
private:
RTPExternalSender *sender;
int headersize;
};
/** Additional information about the external transmission component. */
class JRTPLIB_IMPORTEXPORT RTPExternalTransmissionInfo : public RTPTransmissionInfo
{
public:
RTPExternalTransmissionInfo(RTPExternalPacketInjecter *p) : RTPTransmissionInfo(RTPTransmitter::ExternalProto) { packetinjector = p; }
/** Tells you which RTPExternalPacketInjecter you need to use to pass RTP or RTCP
* data on to the transmission component. */
RTPExternalPacketInjecter *GetPacketInjector() const { return packetinjector; }
private:
RTPExternalPacketInjecter *packetinjector;
};
/** A transmission component which will use user specified functions to transmit the data and
* which will expose functions to inject received RTP or RTCP data into this component.
* A transmission component which will use user specified functions to transmit the data and
* which will expose functions to inject received RTP or RTCP data into this component. Use
* a class derived from RTPExternalSender to specify the functions which need to be used for
* sending the data. Obtain the RTPExternalTransmissionInfo object associated with this
* transmitter to obtain the functions needed to pass RTP/RTCP packets on to the transmitter.
*/
class JRTPLIB_IMPORTEXPORT RTPExternalTransmitter : public RTPTransmitter
{
public:
RTPExternalTransmitter(RTPMemoryManager *mgr);
~RTPExternalTransmitter();
int Init(bool treadsafe);
int Create(size_t maxpacksize, const RTPTransmissionParams *transparams);
void Destroy();
RTPTransmissionInfo *GetTransmissionInfo();
void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
int GetLocalHostName(uint8_t *buffer,size_t *bufferlength);
bool ComesFromThisTransmitter(const RTPAddress *addr);
size_t GetHeaderOverhead() { return headersize; }
int Poll();
int WaitForIncomingData(const RTPTime &delay,bool *dataavailable = 0);
int AbortWait();
int SendRTPData(const void *data,size_t len);
int SendRTCPData(const void *data,size_t len);
int AddDestination(const RTPAddress &addr);
int DeleteDestination(const RTPAddress &addr);
void ClearDestinations();
bool SupportsMulticasting();
int JoinMulticastGroup(const RTPAddress &addr);
int LeaveMulticastGroup(const RTPAddress &addr);
void LeaveAllMulticastGroups();
int SetReceiveMode(RTPTransmitter::ReceiveMode m);
int AddToIgnoreList(const RTPAddress &addr);
int DeleteFromIgnoreList(const RTPAddress &addr);
void ClearIgnoreList();
int AddToAcceptList(const RTPAddress &addr);
int DeleteFromAcceptList(const RTPAddress &addr);
void ClearAcceptList();
int SetMaximumPacketSize(size_t s);
bool NewDataAvailable();
RTPRawPacket *GetNextPacket();
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
void InjectRTP(const void *data, size_t len, const RTPAddress &a);
void InjectRTCP(const void *data, size_t len, const RTPAddress &a);
void InjectRTPorRTCP(const void *data, size_t len, const RTPAddress &a);
private:
void FlushPackets();
bool init;
bool created;
bool waitingfordata;
RTPExternalSender *sender;
RTPExternalPacketInjecter packetinjector;
std::list<RTPRawPacket*> rawpacketlist;
uint8_t *localhostname;
size_t localhostnamelength;
size_t maxpacksize;
int headersize;
// notification descriptors for AbortWait (0 is for reading, 1 for writing)
#if (defined(WIN32) || defined(_WIN32_WCE))
SOCKET abortdesc[2];
#else
int abortdesc[2];
#endif // WIN32
int CreateAbortDescriptors();
void DestroyAbortDescriptors();
void AbortWaitInternal();
#ifdef RTP_SUPPORT_THREAD
jthread::JMutex mainmutex,waitmutex;
int threadsafe;
#endif // RTP_SUPPORT_THREAD
};
inline void RTPExternalPacketInjecter::InjectRTP(const void *data, size_t len, const RTPAddress &a)
{
transmitter->InjectRTP(data, len, a);
}
inline void RTPExternalPacketInjecter::InjectRTCP(const void *data, size_t len, const RTPAddress &a)
{
transmitter->InjectRTCP(data, len, a);
}
inline void RTPExternalPacketInjecter::InjectRTPorRTCP(const void *data, size_t len, const RTPAddress &a)
{
transmitter->InjectRTPorRTCP(data, len, a);
}
} // end namespace
#endif // RTPTCPSOCKETTRANSMITTER_H

View File

@@ -0,0 +1,342 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPHASHTABLE_H
#define RTPHASHTABLE_H
/**
* \file rtphashtable.h
*/
#include "rtperrors.h"
#include "rtpmemoryobject.h"
#ifdef RTPDEBUG
#include <iostream>
#endif // RTPDEBUG
namespace jrtplib
{
//template<class Element,int GetIndex(const Element &k),int hashsize>
template<class Element,class GetIndex,int hashsize>
class RTPHashTable : public RTPMemoryObject
{
public:
RTPHashTable(RTPMemoryManager *mgr = 0, int memtype = RTPMEM_TYPE_OTHER);
~RTPHashTable() { Clear(); }
void GotoFirstElement() { curhashelem = firsthashelem; }
void GotoLastElement() { curhashelem = lasthashelem; }
bool HasCurrentElement() { return (curhashelem == 0)?false:true; }
int DeleteCurrentElement();
Element &GetCurrentElement() { return curhashelem->GetElement(); }
int GotoElement(const Element &e);
bool HasElement(const Element &e);
void GotoNextElement();
void GotoPreviousElement();
void Clear();
int AddElement(const Element &elem);
int DeleteElement(const Element &elem);
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
private:
class HashElement
{
public:
HashElement(const Element &e,int index):element(e) { hashprev = 0; hashnext = 0; listnext = 0; listprev = 0; hashindex = index; }
int GetHashIndex() { return hashindex; }
Element &GetElement() { return element; }
#ifdef RTPDEBUG
void Dump() { std::cout << "\tHash index " << hashindex << " | Element " << element << std::endl; }
#endif // RTPDEBUG
private:
int hashindex;
Element element;
public:
HashElement *hashprev,*hashnext;
HashElement *listprev,*listnext;
};
HashElement *table[hashsize];
HashElement *firsthashelem,*lasthashelem;
HashElement *curhashelem;
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
int memorytype;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
};
template<class Element,class GetIndex,int hashsize>
inline RTPHashTable<Element,GetIndex,hashsize>::RTPHashTable(RTPMemoryManager *mgr,int memtype) : RTPMemoryObject(mgr)
{
for (int i = 0 ; i < hashsize ; i++)
table[i] = 0;
firsthashelem = 0;
lasthashelem = 0;
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
memorytype = memtype;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
}
template<class Element,class GetIndex,int hashsize>
inline int RTPHashTable<Element,GetIndex,hashsize>::DeleteCurrentElement()
{
if (curhashelem)
{
HashElement *tmp1,*tmp2;
int index;
// First, relink elements in current hash bucket
index = curhashelem->GetHashIndex();
tmp1 = curhashelem->hashprev;
tmp2 = curhashelem->hashnext;
if (tmp1 == 0) // no previous element in hash bucket
{
table[index] = tmp2;
if (tmp2 != 0)
tmp2->hashprev = 0;
}
else // there is a previous element in the hash bucket
{
tmp1->hashnext = tmp2;
if (tmp2 != 0)
tmp2->hashprev = tmp1;
}
// Relink elements in list
tmp1 = curhashelem->listprev;
tmp2 = curhashelem->listnext;
if (tmp1 == 0) // curhashelem is first in list
{
firsthashelem = tmp2;
if (tmp2 != 0)
tmp2->listprev = 0;
else // curhashelem is also last in list
lasthashelem = 0;
}
else
{
tmp1->listnext = tmp2;
if (tmp2 != 0)
tmp2->listprev = tmp1;
else // curhashelem is last in list
lasthashelem = tmp1;
}
// finally, with everything being relinked, we can delete curhashelem
RTPDelete(curhashelem,GetMemoryManager());
curhashelem = tmp2; // Set to next element in the list
}
else
return ERR_RTP_HASHTABLE_NOCURRENTELEMENT;
return 0;
}
template<class Element,class GetIndex,int hashsize>
inline int RTPHashTable<Element,GetIndex,hashsize>::GotoElement(const Element &e)
{
int index;
bool found;
index = GetIndex::GetIndex(e);
if (index >= hashsize)
return ERR_RTP_HASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
curhashelem = table[index];
found = false;
while(!found && curhashelem != 0)
{
if (curhashelem->GetElement() == e)
found = true;
else
curhashelem = curhashelem->hashnext;
}
if (!found)
return ERR_RTP_HASHTABLE_ELEMENTNOTFOUND;
return 0;
}
template<class Element,class GetIndex,int hashsize>
inline bool RTPHashTable<Element,GetIndex,hashsize>::HasElement(const Element &e)
{
int index;
bool found;
HashElement *tmp;
index = GetIndex::GetIndex(e);
if (index >= hashsize)
return false;
tmp = table[index];
found = false;
while(!found && tmp != 0)
{
if (tmp->GetElement() == e)
found = true;
else
tmp = tmp->hashnext;
}
return found;
}
template<class Element,class GetIndex,int hashsize>
inline void RTPHashTable<Element,GetIndex,hashsize>::GotoNextElement()
{
if (curhashelem)
curhashelem = curhashelem->listnext;
}
template<class Element,class GetIndex,int hashsize>
inline void RTPHashTable<Element,GetIndex,hashsize>::GotoPreviousElement()
{
if (curhashelem)
curhashelem = curhashelem->listprev;
}
template<class Element,class GetIndex,int hashsize>
inline void RTPHashTable<Element,GetIndex,hashsize>::Clear()
{
HashElement *tmp1,*tmp2;
for (int i = 0 ; i < hashsize ; i++)
table[i] = 0;
tmp1 = firsthashelem;
while (tmp1 != 0)
{
tmp2 = tmp1->listnext;
RTPDelete(tmp1,GetMemoryManager());
tmp1 = tmp2;
}
firsthashelem = 0;
lasthashelem = 0;
}
template<class Element,class GetIndex,int hashsize>
inline int RTPHashTable<Element,GetIndex,hashsize>::AddElement(const Element &elem)
{
int index;
bool found;
HashElement *e,*newelem;
index = GetIndex::GetIndex(elem);
if (index >= hashsize)
return ERR_RTP_HASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
e = table[index];
found = false;
while(!found && e != 0)
{
if (e->GetElement() == elem)
found = true;
else
e = e->hashnext;
}
if (found)
return ERR_RTP_HASHTABLE_ELEMENTALREADYEXISTS;
// Okay, the key doesn't exist, so we can add the new element in the hash table
newelem = RTPNew(GetMemoryManager(),memorytype) HashElement(elem,index);
if (newelem == 0)
return ERR_RTP_OUTOFMEM;
e = table[index];
table[index] = newelem;
newelem->hashnext = e;
if (e != 0)
e->hashprev = newelem;
// Now, we still got to add it to the linked list
if (firsthashelem == 0)
{
firsthashelem = newelem;
lasthashelem = newelem;
}
else // there already are some elements in the list
{
lasthashelem->listnext = newelem;
newelem->listprev = lasthashelem;
lasthashelem = newelem;
}
return 0;
}
template<class Element,class GetIndex,int hashsize>
inline int RTPHashTable<Element,GetIndex,hashsize>::DeleteElement(const Element &elem)
{
int status;
status = GotoElement(elem);
if (status < 0)
return status;
return DeleteCurrentElement();
}
#ifdef RTPDEBUG
template<class Element,class GetIndex,int hashsize>
inline void RTPHashTable<Element,GetIndex,hashsize>::Dump()
{
HashElement *e;
std::cout << "DUMPING TABLE CONTENTS:" << std::endl;
for (int i = 0 ; i < hashsize ; i++)
{
e = table[i];
while (e != 0)
{
e->Dump();
e = e->hashnext;
}
}
std::cout << "DUMPING LIST CONTENTS:" << std::endl;
e = firsthashelem;
while (e != 0)
{
e->Dump();
e = e->listnext;
}
}
#endif // RTPDEBUG
} // end namespace
#endif // RTPHASHTABLE_H

View File

@@ -0,0 +1,287 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpinternalsourcedata.h"
#include "rtppacket.h"
#include <string.h>
#include "rtpdebug.h"
#define RTPINTERNALSOURCEDATA_MAXPROBATIONPACKETS 32
namespace jrtplib
{
RTPInternalSourceData::RTPInternalSourceData(uint32_t ssrc,RTPSources::ProbationType probtype,RTPMemoryManager *mgr):RTPSourceData(ssrc,mgr)
{
#ifdef RTP_SUPPORT_PROBATION
probationtype = probtype;
#endif // RTP_SUPPORT_PROBATION
}
RTPInternalSourceData::~RTPInternalSourceData()
{
}
// The following function should delete rtppack if necessary
int RTPInternalSourceData::ProcessRTPPacket(RTPPacket *rtppack,const RTPTime &receivetime,bool *stored)
{
bool accept,onprobation,applyprobation;
double tsunit;
*stored = false;
if (timestampunit < 0)
tsunit = INF_GetEstimatedTimestampUnit();
else
tsunit = timestampunit;
#ifdef RTP_SUPPORT_PROBATION
if (validated) // If the source is our own process, we can already be validated. No
applyprobation = false; // probation should be applied in that case.
else
{
if (probationtype == RTPSources::NoProbation)
applyprobation = false;
else
applyprobation = true;
}
#else
applyprobation = false;
#endif // RTP_SUPPORT_PROBATION
stats.ProcessPacket(rtppack,receivetime,tsunit,ownssrc,&accept,applyprobation,&onprobation);
#ifdef RTP_SUPPORT_PROBATION
switch (probationtype)
{
case RTPSources::ProbationStore:
if (!(onprobation || accept))
return 0;
if (accept)
validated = true;
break;
case RTPSources::ProbationDiscard:
case RTPSources::NoProbation:
if (!accept)
return 0;
validated = true;
break;
default:
return ERR_RTP_INTERNALSOURCEDATA_INVALIDPROBATIONTYPE;
}
#else
if (!accept)
return 0;
validated = true;
#endif // RTP_SUPPORT_PROBATION;
if (validated && !ownssrc) // for own ssrc these variables depend on the outgoing packets, not on the incoming
issender = true;
// Now, we can place the packet in the queue
if (packetlist.empty())
{
*stored = true;
packetlist.push_back(rtppack);
return 0;
}
if (!validated) // still on probation
{
// Make sure that we don't buffer too much packets to avoid wasting memory
// on a bad source. Delete the packet in the queue with the lowest sequence
// number.
if (packetlist.size() == RTPINTERNALSOURCEDATA_MAXPROBATIONPACKETS)
{
RTPPacket *p = *(packetlist.begin());
packetlist.pop_front();
RTPDelete(p,GetMemoryManager());
}
}
// find the right position to insert the packet
std::list<RTPPacket*>::iterator it,start;
bool done = false;
uint32_t newseqnr = rtppack->GetExtendedSequenceNumber();
it = packetlist.end();
--it;
start = packetlist.begin();
while (!done)
{
RTPPacket *p;
uint32_t seqnr;
p = *it;
seqnr = p->GetExtendedSequenceNumber();
if (seqnr > newseqnr)
{
if (it != start)
--it;
else // we're at the start of the list
{
*stored = true;
done = true;
packetlist.push_front(rtppack);
}
}
else if (seqnr < newseqnr) // insert after this packet
{
++it;
packetlist.insert(it,rtppack);
done = true;
*stored = true;
}
else // they're equal !! Drop packet
{
done = true;
}
}
return 0;
}
int RTPInternalSourceData::ProcessSDESItem(uint8_t sdesid,const uint8_t *data,size_t itemlen,const RTPTime &receivetime,bool *cnamecollis)
{
*cnamecollis = false;
stats.SetLastMessageTime(receivetime);
switch(sdesid)
{
case RTCP_SDES_ID_CNAME:
{
size_t curlen;
uint8_t *oldcname;
// NOTE: we're going to make sure that the CNAME is only set once.
oldcname = SDESinf.GetCNAME(&curlen);
if (curlen == 0)
{
// if CNAME is set, the source is validated
SDESinf.SetCNAME(data,itemlen);
validated = true;
}
else // check if this CNAME is equal to the one that is already present
{
if (curlen != itemlen)
*cnamecollis = true;
else
{
if (memcmp(data,oldcname,itemlen) != 0)
*cnamecollis = true;
}
}
}
break;
case RTCP_SDES_ID_NAME:
{
uint8_t *oldname;
size_t oldlen;
oldname = SDESinf.GetName(&oldlen);
if (oldlen == 0) // Name not set
return SDESinf.SetName(data,itemlen);
}
break;
case RTCP_SDES_ID_EMAIL:
{
uint8_t *oldemail;
size_t oldlen;
oldemail = SDESinf.GetEMail(&oldlen);
if (oldlen == 0)
return SDESinf.SetEMail(data,itemlen);
}
break;
case RTCP_SDES_ID_PHONE:
return SDESinf.SetPhone(data,itemlen);
case RTCP_SDES_ID_LOCATION:
return SDESinf.SetLocation(data,itemlen);
case RTCP_SDES_ID_TOOL:
{
uint8_t *oldtool;
size_t oldlen;
oldtool = SDESinf.GetTool(&oldlen);
if (oldlen == 0)
return SDESinf.SetTool(data,itemlen);
}
break;
case RTCP_SDES_ID_NOTE:
stats.SetLastNoteTime(receivetime);
return SDESinf.SetNote(data,itemlen);
}
return 0;
}
#ifdef RTP_SUPPORT_SDESPRIV
int RTPInternalSourceData::ProcessPrivateSDESItem(const uint8_t *prefix,size_t prefixlen,const uint8_t *value,size_t valuelen,const RTPTime &receivetime)
{
int status;
stats.SetLastMessageTime(receivetime);
status = SDESinf.SetPrivateValue(prefix,prefixlen,value,valuelen);
if (status == ERR_RTP_SDES_MAXPRIVITEMS)
return 0; // don't stop processing just because the number of items is full
return status;
}
#endif // RTP_SUPPORT_SDESPRIV
int RTPInternalSourceData::ProcessBYEPacket(const uint8_t *reason,size_t reasonlen,const RTPTime &receivetime)
{
if (byereason)
{
RTPDeleteByteArray(byereason,GetMemoryManager());
byereason = 0;
byereasonlen = 0;
}
byetime = receivetime;
byereason = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPBYEREASON) uint8_t[reasonlen];
if (byereason == 0)
return ERR_RTP_OUTOFMEM;
memcpy(byereason,reason,reasonlen);
byereasonlen = reasonlen;
receivedbye = true;
stats.SetLastMessageTime(receivetime);
return 0;
}
} // end namespace

View File

@@ -0,0 +1,135 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpinternalsourcedata.h
*/
#ifndef RTPINTERNALSOURCEDATA_H
#define RTPINTERNALSOURCEDATA_H
#include "rtpconfig.h"
#include "rtpsourcedata.h"
#include "rtpaddress.h"
#include "rtptimeutilities.h"
#include "rtpsources.h"
namespace jrtplib
{
class JRTPLIB_IMPORTEXPORT RTPInternalSourceData : public RTPSourceData
{
public:
RTPInternalSourceData(uint32_t ssrc, RTPSources::ProbationType probtype, RTPMemoryManager *mgr = 0);
~RTPInternalSourceData();
int ProcessRTPPacket(RTPPacket *rtppack,const RTPTime &receivetime,bool *stored);
void ProcessSenderInfo(const RTPNTPTime &ntptime,uint32_t rtptime,uint32_t packetcount,
uint32_t octetcount,const RTPTime &receivetime) { SRprevinf = SRinf; SRinf.Set(ntptime,rtptime,packetcount,octetcount,receivetime); stats.SetLastMessageTime(receivetime); }
void ProcessReportBlock(uint8_t fractionlost,int32_t lostpackets,uint32_t exthighseqnr,
uint32_t jitter,uint32_t lsr,uint32_t dlsr,
const RTPTime &receivetime) { RRprevinf = RRinf; RRinf.Set(fractionlost,lostpackets,exthighseqnr,jitter,lsr,dlsr,receivetime); stats.SetLastMessageTime(receivetime); }
void UpdateMessageTime(const RTPTime &receivetime) { stats.SetLastMessageTime(receivetime); }
int ProcessSDESItem(uint8_t sdesid,const uint8_t *data,size_t itemlen,const RTPTime &receivetime,bool *cnamecollis);
#ifdef RTP_SUPPORT_SDESPRIV
int ProcessPrivateSDESItem(const uint8_t *prefix,size_t prefixlen,const uint8_t *value,size_t valuelen,const RTPTime &receivetime);
#endif // RTP_SUPPORT_SDESPRIV
int ProcessBYEPacket(const uint8_t *reason,size_t reasonlen,const RTPTime &receivetime);
int SetRTPDataAddress(const RTPAddress *a);
int SetRTCPDataAddress(const RTPAddress *a);
void ClearSenderFlag() { issender = false; }
void SentRTPPacket() { if (!ownssrc) return; RTPTime t = RTPTime::CurrentTime(); issender = true; stats.SetLastRTPPacketTime(t); stats.SetLastMessageTime(t); }
void SetOwnSSRC() { ownssrc = true; validated = true; }
void SetCSRC() { validated = true; iscsrc = true; }
void ClearNote() { SDESinf.SetNote(0,0); }
#ifdef RTP_SUPPORT_PROBATION
private:
RTPSources::ProbationType probationtype;
#endif // RTP_SUPPORT_PROBATION
};
inline int RTPInternalSourceData::SetRTPDataAddress(const RTPAddress *a)
{
if (a == 0)
{
if (rtpaddr)
{
RTPDelete(rtpaddr,GetMemoryManager());
rtpaddr = 0;
}
}
else
{
RTPAddress *newaddr = a->CreateCopy(GetMemoryManager());
if (newaddr == 0)
return ERR_RTP_OUTOFMEM;
if (rtpaddr && a != rtpaddr)
RTPDelete(rtpaddr,GetMemoryManager());
rtpaddr = newaddr;
}
isrtpaddrset = true;
return 0;
}
inline int RTPInternalSourceData::SetRTCPDataAddress(const RTPAddress *a)
{
if (a == 0)
{
if (rtcpaddr)
{
RTPDelete(rtcpaddr,GetMemoryManager());
rtcpaddr = 0;
}
}
else
{
RTPAddress *newaddr = a->CreateCopy(GetMemoryManager());
if (newaddr == 0)
return ERR_RTP_OUTOFMEM;
if (rtcpaddr && a != rtcpaddr)
RTPDelete(rtcpaddr,GetMemoryManager());
rtcpaddr = newaddr;
}
isrtcpaddrset = true;
return 0;
}
} // end namespace
#endif // RTPINTERNALSOURCEDATA_H

View File

@@ -0,0 +1,111 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpipv4address.h"
#include "rtpmemorymanager.h"
#ifdef RTPDEBUG
#include "rtpdefines.h"
#include <stdio.h>
#endif // RTPDEBUG
#include "rtpdebug.h"
namespace jrtplib
{
RTPIPv4Address::RTPIPv4Address(uint32_t ip, uint16_t port)
:RTPAddress(IPv4Address)
{
RTPIPv4Address::ip = ip;
RTPIPv4Address::port = port;
}
RTPIPv4Address::RTPIPv4Address(const uint8_t ip[4],uint16_t port)
:RTPAddress(IPv4Address)
{
RTPIPv4Address::ip = (uint32_t)ip[3];
RTPIPv4Address::ip |= (((uint32_t)ip[2])<<8);
RTPIPv4Address::ip |= (((uint32_t)ip[1])<<16);
RTPIPv4Address::ip |= (((uint32_t)ip[0])<<24);
RTPIPv4Address::port = port;
}
RTPIPv4Address::~RTPIPv4Address()
{
}
bool RTPIPv4Address::IsSameAddress(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != IPv4Address)
return false;
const RTPIPv4Address *addr2 = (const RTPIPv4Address *)addr;
if (addr2->GetIP() == ip && addr2->GetPort() == port)
return true;
return false;
}
bool RTPIPv4Address::IsFromSameHost(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != IPv4Address)
return false;
const RTPIPv4Address *addr2 = (const RTPIPv4Address *)addr;
if (addr2->GetIP() == ip)
return true;
return false;
}
RTPAddress *RTPIPv4Address::CreateCopy(RTPMemoryManager *mgr) const
{
RTPIPv4Address *a = RTPNew(mgr,RTPMEM_TYPE_CLASS_RTPADDRESS) RTPIPv4Address(ip,port);
return a;
}
#ifdef RTPDEBUG
std::string RTPIPv4Address::GetAddressString() const
{
char str[24];
RTP_SNPRINTF(str,24,"%d.%d.%d.%d:%d",(int)((ip>>24)&0xFF),(int)((ip>>16)&0xFF),(int)((ip>>8)&0xFF),
(int)(ip&0xFF),(int)port);
return std::string(str);
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,95 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpipv4address.h
*/
#ifndef RTPIPV4ADDRESS_H
#define RTPIPV4ADDRESS_H
#include "rtpconfig.h"
#include "rtpaddress.h"
#include "rtptypes.h"
namespace jrtplib
{
class RTPMemoryManager;
/** Represents an IPv4 IP address and port.
* This class is used by the UDP over IPv4 transmission component.
* When an RTPIPv4Address is used in one of the multicast functions of the transmitter, the port
* number is ignored. When an instance is used in one of the accept or ignore functions of the
* transmitter, a zero port number represents all ports for the specified IP address.
*/
class JRTPLIB_IMPORTEXPORT RTPIPv4Address : public RTPAddress
{
public:
/** Creates an instance with IP address \c ip and port number \c port (both are interpreted in host byte order). */
RTPIPv4Address(uint32_t ip = 0, uint16_t port = 0);
/** Creates an instance with IP address \c ip and port number \c port (\c port is interpreted in host byte order). */
RTPIPv4Address(const uint8_t ip[4],uint16_t port = 0);
~RTPIPv4Address();
/** Sets the IP address for this instance to \c ip which is assumed to be in host byte order. */
void SetIP(uint32_t ip) { RTPIPv4Address::ip = ip; }
/** Sets the IP address of this instance to \c ip. */
void SetIP(const uint8_t ip[4]) { RTPIPv4Address::ip = (uint32_t)ip[3]; RTPIPv4Address::ip |= (((uint32_t)ip[2])<<8); RTPIPv4Address::ip |= (((uint32_t)ip[1])<<16); RTPIPv4Address::ip |= (((uint32_t)ip[0])<<24); }
/** Sets the port number for this instance to \c port which is interpreted in host byte order. */
void SetPort(uint16_t port) { RTPIPv4Address::port = port; }
/** Returns the IP address contained in this instance in host byte order. */
uint32_t GetIP() const { return ip; }
/** Returns the port number of this instance in host byte order. */
uint16_t GetPort() const { return port; }
RTPAddress *CreateCopy(RTPMemoryManager *mgr) const;
bool IsSameAddress(const RTPAddress *addr) const;
bool IsFromSameHost(const RTPAddress *addr) const;
#ifdef RTPDEBUG
std::string GetAddressString() const;
#endif // RTPDEBUG
private:
uint32_t ip;
uint16_t port;
};
} // end namespace
#endif // RTPIPV4ADDRESS_H

View File

@@ -0,0 +1,113 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpipv4destination.h
*/
#ifndef RTPIPV4DESTINATION_H
#define RTPIPV4DESTINATION_H
#include "rtpconfig.h"
#if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif // WIN32
#ifdef RTPDEBUG
#include "rtpdefines.h"
#include <stdio.h>
#include <string>
#endif // RTPDEBUG
#include <string.h>
namespace jrtplib
{
class JRTPLIB_IMPORTEXPORT RTPIPv4Destination
{
public:
RTPIPv4Destination(uint32_t ip,uint16_t rtpportbase)
{
memset(&rtpaddr,0,sizeof(struct sockaddr_in));
memset(&rtcpaddr,0,sizeof(struct sockaddr_in));
rtpaddr.sin_family = AF_INET;
rtpaddr.sin_port = htons(rtpportbase);
rtpaddr.sin_addr.s_addr = htonl(ip);
rtcpaddr.sin_family = AF_INET;
rtcpaddr.sin_port = htons(rtpportbase+1);
rtcpaddr.sin_addr.s_addr = htonl(ip);
RTPIPv4Destination::ip = ip;
}
bool operator==(const RTPIPv4Destination &src) const
{
if (rtpaddr.sin_addr.s_addr == src.rtpaddr.sin_addr.s_addr && rtpaddr.sin_port == src.rtpaddr.sin_port)
return true;
return false;
}
uint32_t GetIP() const { return ip; }
// nbo = network byte order
uint32_t GetIP_NBO() const { return rtpaddr.sin_addr.s_addr; }
uint16_t GetRTPPort_NBO() const { return rtpaddr.sin_port; }
uint16_t GetRTCPPort_NBO() const { return rtcpaddr.sin_port; }
const struct sockaddr_in *GetRTPSockAddr() const { return &rtpaddr; }
const struct sockaddr_in *GetRTCPSockAddr() const { return &rtcpaddr; }
#ifdef RTPDEBUG
std::string GetDestinationString() const;
#endif // RTPDEBUG
private:
uint32_t ip;
struct sockaddr_in rtpaddr;
struct sockaddr_in rtcpaddr;
};
#ifdef RTPDEBUG
inline std::string RTPIPv4Destination::GetDestinationString() const
{
char str[24];
uint32_t ip = GetIP();
uint16_t portbase = ntohs(GetRTPPort_NBO());
RTP_SNPRINTF(str,24,"%d.%d.%d.%d:%d",(int)((ip>>24)&0xFF),(int)((ip>>16)&0xFF),(int)((ip>>8)&0xFF),(int)(ip&0xFF),(int)(portbase));
return std::string(str);
}
#endif // RTPDEBUG
} // end namespace
#endif // RTPIPV4DESTINATION_H

View File

@@ -0,0 +1,113 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpipv6address.h"
#include "rtpmemorymanager.h"
#ifdef RTP_SUPPORT_IPV6
#ifdef RTPDEBUG
#include "rtpdefines.h"
#include <stdio.h>
#endif // RTPDEBUG
#include "rtpdebug.h"
namespace jrtplib
{
RTPAddress *RTPIPv6Address::CreateCopy(RTPMemoryManager *mgr) const
{
RTPIPv6Address *newaddr = RTPNew(mgr,RTPMEM_TYPE_CLASS_RTPADDRESS) RTPIPv6Address(ip,port);
return newaddr;
}
bool RTPIPv6Address::IsSameAddress(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != RTPAddress::IPv6Address)
return false;
const RTPIPv6Address *addr2 = (const RTPIPv6Address *)addr;
const uint8_t *ip2 = addr2->ip.s6_addr;
if (port != addr2->port)
return false;
for (int i = 0 ; i < 16 ; i++)
{
if (ip.s6_addr[i] != ip2[i])
return false;
}
return true;
}
bool RTPIPv6Address::IsFromSameHost(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != RTPAddress::IPv6Address)
return false;
const RTPIPv6Address *addr2 = (const RTPIPv6Address *)addr;
const uint8_t *ip2 = addr2->ip.s6_addr;
for (int i = 0 ; i < 16 ; i++)
{
if (ip.s6_addr[i] != ip2[i])
return false;
}
return true;
}
#ifdef RTPDEBUG
std::string RTPIPv6Address::GetAddressString() const
{
char str[48];
uint16_t ip16[8];
int i,j;
for (i = 0,j = 0 ; j < 8 ; j++,i += 2)
{
ip16[j] = (((uint16_t)ip.s6_addr[i])<<8);
ip16[j] |= ((uint16_t)ip.s6_addr[i+1]);
}
RTP_SNPRINTF(str,48,"%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X/%d",(int)ip16[0],(int)ip16[1],(int)ip16[2],(int)ip16[3],(int)ip16[4],(int)ip16[5],(int)ip16[6],(int)ip16[7],(int)port);
return std::string(str);
}
#endif // RTPDEBUG
} // end namespace
#endif // RTP_SUPPORT_IPV6

View File

@@ -0,0 +1,110 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpipv6address.h
*/
#ifndef RTPIPV6ADDRESS_H
#define RTPIPV6ADDRESS_H
#include "rtpconfig.h"
#ifdef RTP_SUPPORT_IPV6
#include "rtpaddress.h"
#include "rtptypes.h"
#if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h>
#endif // WIN32
namespace jrtplib
{
/** Represents an IPv6 IP address and port.
* This class is used by the UDP over IPv4 transmission component.
* When an RTPIPv6Address is used in one of the multicast functions of the
* transmitter, the port number is ignored. When an instance is used in one of
* the accept or ignore functions of the transmitter, a zero port number represents
* all ports for the specified IP address.
*/
class JRTPLIB_IMPORTEXPORT RTPIPv6Address : public RTPAddress
{
public:
/** Creates an instance with IP address and port number set to zero. */
RTPIPv6Address():RTPAddress(IPv6Address) { for (int i = 0 ; i < 16 ; i++) ip.s6_addr[i] = 0; port = 0; }
/** Creates an instance with IP address \c ip and port number \c port (the port number is assumed to be in
* host byte order). */
RTPIPv6Address(const uint8_t ip[16],uint16_t port = 0):RTPAddress(IPv6Address) { SetIP(ip); RTPIPv6Address::port = port; }
/** Creates an instance with IP address \c ip and port number \c port (the port number is assumed to be in
* host byte order). */
RTPIPv6Address(in6_addr ip,uint16_t port = 0):RTPAddress(IPv6Address) { RTPIPv6Address::ip = ip; RTPIPv6Address::port = port; }
~RTPIPv6Address() { }
/** Sets the IP address for this instance to \c ip. */
void SetIP(in6_addr ip) { RTPIPv6Address::ip = ip; }
/** Sets the IP address for this instance to \c ip. */
void SetIP(const uint8_t ip[16]) { for (int i = 0 ; i < 16 ; i++) RTPIPv6Address::ip.s6_addr[i] = ip[i]; }
/** Sets the port number for this instance to \c port, which is interpreted in host byte order. */
void SetPort(uint16_t port) { RTPIPv6Address::port = port; }
/** Copies the IP address of this instance in \c ip. */
void GetIP(uint8_t ip[16]) const { for (int i = 0 ; i < 16 ; i++) ip[i] = RTPIPv6Address::ip.s6_addr[i]; }
/** Returns the IP address of this instance. */
in6_addr GetIP() const { return ip; }
/** Returns the port number contained in this instance in host byte order. */
uint16_t GetPort() const { return port; }
RTPAddress *CreateCopy(RTPMemoryManager *mgr) const;
bool IsSameAddress(const RTPAddress *addr) const;
bool IsFromSameHost(const RTPAddress *addr) const;
#ifdef RTPDEBUG
std::string GetAddressString() const;
#endif // RTPDEBUG
private:
in6_addr ip;
uint16_t port;
};
} // end namespace
#endif // RTP_SUPPORT_IPV6
#endif // RTPIPV6ADDRESS_H

View File

@@ -0,0 +1,114 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpipv6destination.h
*/
#ifndef RTPIPV6DESTINATION_H
#define RTPIPV6DESTINATION_H
#include "rtpconfig.h"
#ifdef RTP_SUPPORT_IPV6
#include "rtptypes.h"
#include <string.h>
#ifndef WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif // WIN32
#ifdef RTPDEBUG
#include "rtpdefines.h"
#include <stdio.h>
#include <string>
#endif // RTPDEBUG
namespace jrtplib
{
class JRTPLIB_IMPORTEXPORT RTPIPv6Destination
{
public:
RTPIPv6Destination(in6_addr ip,uint16_t portbase)
{
memset(&rtpaddr,0,sizeof(struct sockaddr_in6));
memset(&rtcpaddr,0,sizeof(struct sockaddr_in6));
rtpaddr.sin6_family = AF_INET6;
rtpaddr.sin6_port = htons(portbase);
rtpaddr.sin6_addr = ip;
rtcpaddr.sin6_family = AF_INET6;
rtcpaddr.sin6_port = htons(portbase+1);
rtcpaddr.sin6_addr = ip;
}
in6_addr GetIP() const { return rtpaddr.sin6_addr; }
bool operator==(const RTPIPv6Destination &src) const
{
if (rtpaddr.sin6_port == src.rtpaddr.sin6_port && (memcmp(&(src.rtpaddr.sin6_addr),&(rtpaddr.sin6_addr),sizeof(in6_addr)) == 0))
return true;
return false;
}
const struct sockaddr_in6 *GetRTPSockAddr() const { return &rtpaddr; }
const struct sockaddr_in6 *GetRTCPSockAddr() const { return &rtcpaddr; }
#ifdef RTPDEBUG
std::string GetDestinationString() const;
#endif // RTPDEBUG
private:
struct sockaddr_in6 rtpaddr;
struct sockaddr_in6 rtcpaddr;
};
#ifdef RTPDEBUG
inline std::string RTPIPv6Destination::GetDestinationString() const
{
uint16_t ip16[8];
char str[48];
uint16_t portbase = ntohs(rtpaddr.sin6_port);
int i,j;
for (i = 0,j = 0 ; j < 8 ; j++,i += 2)
{
ip16[j] = (((uint16_t)rtpaddr.sin6_addr.s6_addr[i])<<8);
ip16[j] |= ((uint16_t)rtpaddr.sin6_addr.s6_addr[i+1]);
}
RTP_SNPRINTF(str,48,"%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X/%d",(int)ip16[0],(int)ip16[1],(int)ip16[2],(int)ip16[3],(int)ip16[4],(int)ip16[5],(int)ip16[6],(int)ip16[7],(int)portbase);
return std::string(str);
}
#endif // RTPDEBUG
} // end namespace
#endif // RTP_SUPPORT_IPV6
#endif // RTPIPV6DESTINATION_H

View File

@@ -0,0 +1,344 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpkeyhashtable.h
*/
#ifndef RTPKEYHASHTABLE_H
#define RTPKEYHASHTABLE_H
#include "rtpconfig.h"
#include "rtperrors.h"
#include "rtpmemoryobject.h"
#ifdef RTPDEBUG
#include <iostream>
#endif // RTPDEBUG
namespace jrtplib
{
template<class Key,class Element,class GetIndex,int hashsize>
class RTPKeyHashTable : public RTPMemoryObject
{
public:
RTPKeyHashTable(RTPMemoryManager *mgr = 0,int memtype = RTPMEM_TYPE_OTHER);
~RTPKeyHashTable() { Clear(); }
void GotoFirstElement() { curhashelem = firsthashelem; }
void GotoLastElement() { curhashelem = lasthashelem; }
bool HasCurrentElement() { return (curhashelem == 0)?false:true; }
int DeleteCurrentElement();
Element &GetCurrentElement() { return curhashelem->GetElement(); }
Key &GetCurrentKey() { return curhashelem->GetKey(); }
int GotoElement(const Key &k);
bool HasElement(const Key &k);
void GotoNextElement();
void GotoPreviousElement();
void Clear();
int AddElement(const Key &k,const Element &elem);
int DeleteElement(const Key &k);
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
private:
class HashElement
{
public:
HashElement(const Key &k,const Element &e,int index):key(k),element(e) { hashprev = 0; hashnext = 0; listnext = 0; listprev = 0; hashindex = index; }
int GetHashIndex() { return hashindex; }
Key &GetKey() { return key; }
Element &GetElement() { return element; }
#ifdef RTPDEBUG
void Dump() { std::cout << "\tHash index " << hashindex << " | Key " << key << " | Element " << element << std::endl; }
#endif // RTPDEBUG
private:
int hashindex;
Key key;
Element element;
public:
HashElement *hashprev,*hashnext;
HashElement *listprev,*listnext;
};
HashElement *table[hashsize];
HashElement *firsthashelem,*lasthashelem;
HashElement *curhashelem;
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
int memorytype;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
};
template<class Key,class Element,class GetIndex,int hashsize>
inline RTPKeyHashTable<Key,Element,GetIndex,hashsize>::RTPKeyHashTable(RTPMemoryManager *mgr,int memtype) : RTPMemoryObject(mgr)
{
for (int i = 0 ; i < hashsize ; i++)
table[i] = 0;
firsthashelem = 0;
lasthashelem = 0;
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
memorytype = memtype;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
}
template<class Key,class Element,class GetIndex,int hashsize>
inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::DeleteCurrentElement()
{
if (curhashelem)
{
HashElement *tmp1,*tmp2;
int index;
// First, relink elements in current hash bucket
index = curhashelem->GetHashIndex();
tmp1 = curhashelem->hashprev;
tmp2 = curhashelem->hashnext;
if (tmp1 == 0) // no previous element in hash bucket
{
table[index] = tmp2;
if (tmp2 != 0)
tmp2->hashprev = 0;
}
else // there is a previous element in the hash bucket
{
tmp1->hashnext = tmp2;
if (tmp2 != 0)
tmp2->hashprev = tmp1;
}
// Relink elements in list
tmp1 = curhashelem->listprev;
tmp2 = curhashelem->listnext;
if (tmp1 == 0) // curhashelem is first in list
{
firsthashelem = tmp2;
if (tmp2 != 0)
tmp2->listprev = 0;
else // curhashelem is also last in list
lasthashelem = 0;
}
else
{
tmp1->listnext = tmp2;
if (tmp2 != 0)
tmp2->listprev = tmp1;
else // curhashelem is last in list
lasthashelem = tmp1;
}
// finally, with everything being relinked, we can delete curhashelem
RTPDelete(curhashelem,GetMemoryManager());
curhashelem = tmp2; // Set to next element in list
}
else
return ERR_RTP_KEYHASHTABLE_NOCURRENTELEMENT;
return 0;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoElement(const Key &k)
{
int index;
bool found;
index = GetIndex::GetIndex(k);
if (index >= hashsize)
return ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
curhashelem = table[index];
found = false;
while(!found && curhashelem != 0)
{
if (curhashelem->GetKey() == k)
found = true;
else
curhashelem = curhashelem->hashnext;
}
if (!found)
return ERR_RTP_KEYHASHTABLE_KEYNOTFOUND;
return 0;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline bool RTPKeyHashTable<Key,Element,GetIndex,hashsize>::HasElement(const Key &k)
{
int index;
bool found;
HashElement *tmp;
index = GetIndex::GetIndex(k);
if (index >= hashsize)
return false;
tmp = table[index];
found = false;
while(!found && tmp != 0)
{
if (tmp->GetKey() == k)
found = true;
else
tmp = tmp->hashnext;
}
return found;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoNextElement()
{
if (curhashelem)
curhashelem = curhashelem->listnext;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoPreviousElement()
{
if (curhashelem)
curhashelem = curhashelem->listprev;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::Clear()
{
HashElement *tmp1,*tmp2;
for (int i = 0 ; i < hashsize ; i++)
table[i] = 0;
tmp1 = firsthashelem;
while (tmp1 != 0)
{
tmp2 = tmp1->listnext;
RTPDelete(tmp1,GetMemoryManager());
tmp1 = tmp2;
}
firsthashelem = 0;
lasthashelem = 0;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::AddElement(const Key &k,const Element &elem)
{
int index;
bool found;
HashElement *e,*newelem;
index = GetIndex::GetIndex(k);
if (index >= hashsize)
return ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
e = table[index];
found = false;
while(!found && e != 0)
{
if (e->GetKey() == k)
found = true;
else
e = e->hashnext;
}
if (found)
return ERR_RTP_KEYHASHTABLE_KEYALREADYEXISTS;
// Okay, the key doesn't exist, so we can add the new element in the hash table
newelem = RTPNew(GetMemoryManager(),memorytype) HashElement(k,elem,index);
if (newelem == 0)
return ERR_RTP_OUTOFMEM;
e = table[index];
table[index] = newelem;
newelem->hashnext = e;
if (e != 0)
e->hashprev = newelem;
// Now, we still got to add it to the linked list
if (firsthashelem == 0)
{
firsthashelem = newelem;
lasthashelem = newelem;
}
else // there already are some elements in the list
{
lasthashelem->listnext = newelem;
newelem->listprev = lasthashelem;
lasthashelem = newelem;
}
return 0;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::DeleteElement(const Key &k)
{
int status;
status = GotoElement(k);
if (status < 0)
return status;
return DeleteCurrentElement();
}
#ifdef RTPDEBUG
template<class Key,class Element,class GetIndex,int hashsize>
inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::Dump()
{
HashElement *e;
std::cout << "DUMPING TABLE CONTENTS:" << std::endl;
for (int i = 0 ; i < hashsize ; i++)
{
e = table[i];
while (e != 0)
{
e->Dump();
e = e->hashnext;
}
}
std::cout << "DUMPING LIST CONTENTS:" << std::endl;
e = firsthashelem;
while (e != 0)
{
e->Dump();
e = e->listnext;
}
}
#endif // RTPDEBUG
} // end namespace
#endif // RTPKEYHASHTABLE_H

View File

@@ -0,0 +1,55 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtplibraryversion.h"
#include "rtpdefines.h"
#include <stdio.h>
namespace jrtplib
{
RTPLibraryVersion RTPLibraryVersion::GetVersion()
{
return RTPLibraryVersion(3,9,1);
}
std::string RTPLibraryVersion::GetVersionString() const
{
char str[16];
RTP_SNPRINTF(str,16,"%d.%d.%d",majornr,minornr,debugnr);
return std::string(str);
}
} // end namespace

View File

@@ -0,0 +1,77 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtplibraryversion.h
*/
#ifndef RTPLIBRARYVERSION_H
#define RTPLIBRARYVERSION_H
#include "rtpconfig.h"
#include <string>
#include <stdio.h>
namespace jrtplib
{
/**
* Used to provide information about the version of the library.
*/
class JRTPLIB_IMPORTEXPORT RTPLibraryVersion
{
public:
/** Returns an instance of RTPLibraryVersion describing the version of the library. */
static RTPLibraryVersion GetVersion();
private:
RTPLibraryVersion(int major,int minor,int debug) { majornr = major; minornr = minor; debugnr = debug; }
public:
/** Returns the major version number. */
int GetMajorNumber() const { return majornr; }
/** Returns the minor version number. */
int GetMinorNumber() const { return minornr; }
/** Returns the debug version number. */
int GetDebugNumber() const { return debugnr; }
/** Returns a string describing the library version. */
std::string GetVersionString() const;
private:
int debugnr,minornr,majornr;
};
} // end namespace
#endif // RTPLIBRARYVERSION_H

View File

@@ -0,0 +1,257 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpmemorymanager.h
*/
#ifndef RTPMEMORYMANAGER_H
#define RTPMEMORYMANAGER_H
#include "rtpconfig.h"
#include "rtptypes.h"
/** Used to indicate a general kind of memory block. */
#define RTPMEM_TYPE_OTHER 0
/** Buffer to store an incoming RTP packet. */
#define RTPMEM_TYPE_BUFFER_RECEIVEDRTPPACKET 1
/** Buffer to store an incoming RTCP packet. */
#define RTPMEM_TYPE_BUFFER_RECEIVEDRTCPPACKET 2
/** Buffer to store an RTCP APP packet. */
#define RTPMEM_TYPE_BUFFER_RTCPAPPPACKET 3
/** Buffer to store an RTCP BYE packet. */
#define RTPMEM_TYPE_BUFFER_RTCPBYEPACKET 4
/** Buffer to store a BYE reason. */
#define RTPMEM_TYPE_BUFFER_RTCPBYEREASON 5
/** Buffer to store an RTCP compound packet. */
#define RTPMEM_TYPE_BUFFER_RTCPCOMPOUNDPACKET 6
/** Buffer to store an SDES block. */
#define RTPMEM_TYPE_BUFFER_RTCPSDESBLOCK 7
/** Buffer to store an RTP packet. */
#define RTPMEM_TYPE_BUFFER_RTPPACKET 8
/** Buffer used by an RTPPacketBuilder instance. */
#define RTPMEM_TYPE_BUFFER_RTPPACKETBUILDERBUFFER 9
/** Buffer to store an SDES item. */
#define RTPMEM_TYPE_BUFFER_SDESITEM 10
/** Hash element used in the accept/ignore table. */
#define RTPMEM_TYPE_CLASS_ACCEPTIGNOREHASHELEMENT 11
/** Buffer to store a PortInfo instance, used by the UDP over IPv4 and IPv6 transmitters. */
#define RTPMEM_TYPE_CLASS_ACCEPTIGNOREPORTINFO 12
/** Buffer to store a HashElement instance for the destination hash table. */
#define RTPMEM_TYPE_CLASS_DESTINATIONLISTHASHELEMENT 13
/** Buffer to store a HashElement instance for the multicast hash table. */
#define RTPMEM_TYPE_CLASS_MULTICASTHASHELEMENT 14
/** Buffer to store an instance of RTCPAPPPacket. */
#define RTPMEM_TYPE_CLASS_RTCPAPPPACKET 15
/** Buffer to store an instance of RTCPBYEPacket. */
#define RTPMEM_TYPE_CLASS_RTCPBYEPACKET 16
/** Buffer to store an instance of RTCPCompoundPacketBuilder. */
#define RTPMEM_TYPE_CLASS_RTCPCOMPOUNDPACKETBUILDER 17
/** Buffer to store an RTCPReceiverReport instance. */
#define RTPMEM_TYPE_CLASS_RTCPRECEIVERREPORT 18
/** Buffer to store an instance of RTCPRRPacket. */
#define RTPMEM_TYPE_CLASS_RTCPRRPACKET 19
/** Buffer to store an instance of RTCPSDESPacket. */
#define RTPMEM_TYPE_CLASS_RTCPSDESPACKET 20
/** Buffer to store an instance of RTCPSRPacket. */
#define RTPMEM_TYPE_CLASS_RTCPSRPACKET 21
/** Buffer to store an instance of RTCPUnknownPacket. */
#define RTPMEM_TYPE_CLASS_RTCPUNKNOWNPACKET 22
/** Buffer to store an instance of an RTPAddress derived class. */
#define RTPMEM_TYPE_CLASS_RTPADDRESS 23
/** Buffer to store an instance of RTPInternalSourceData. */
#define RTPMEM_TYPE_CLASS_RTPINTERNALSOURCEDATA 24
/** Buffer to store an RTPPacket instance. */
#define RTPMEM_TYPE_CLASS_RTPPACKET 25
/** Buffer to store an RTPPollThread instance. */
#define RTPMEM_TYPE_CLASS_RTPPOLLTHREAD 26
/** Buffer to store an RTPRawPacket instance. */
#define RTPMEM_TYPE_CLASS_RTPRAWPACKET 27
/** Buffer to store an RTPTransmissionInfo derived class. */
#define RTPMEM_TYPE_CLASS_RTPTRANSMISSIONINFO 28
/** Buffer to store an RTPTransmitter derived class. */
#define RTPMEM_TYPE_CLASS_RTPTRANSMITTER 29
/** Buffer to store an SDESPrivateItem instance. */
#define RTPMEM_TYPE_CLASS_SDESPRIVATEITEM 30
/** Buffer to store an SDESSource instance. */
#define RTPMEM_TYPE_CLASS_SDESSOURCE 31
/** Buffer to store a HashElement instance for the source table. */
#define RTPMEM_TYPE_CLASS_SOURCETABLEHASHELEMENT 32
namespace jrtplib
{
/** A memory manager. */
class JRTPLIB_IMPORTEXPORT RTPMemoryManager
{
public:
RTPMemoryManager() { }
virtual ~RTPMemoryManager() { }
/** Called to allocate \c numbytes of memory.
* Called to allocate \c numbytes of memory. The \c memtype parameter
* indicates what the purpose of the memory block is. Relevant values
* can be found in rtpmemorymanager.h . Note that the types starting with
* \c RTPMEM_TYPE_CLASS indicate fixed size buffers and that types starting
* with \c RTPMEM_TYPE_BUFFER indicate variable size buffers.
*/
virtual void *AllocateBuffer(size_t numbytes, int memtype) = 0;
/** Frees the previously allocated memory block \c buffer */
virtual void FreeBuffer(void *buffer) = 0;
};
} // end namespace
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
#include <new>
inline void *operator new(size_t numbytes, jrtplib::RTPMemoryManager *mgr, int memtype)
{
if (mgr == 0)
return operator new(numbytes);
return mgr->AllocateBuffer(numbytes,memtype);
}
inline void operator delete(void *buffer, jrtplib::RTPMemoryManager *mgr, int memtype)
{
if (mgr == 0)
operator delete(buffer);
else
mgr->FreeBuffer(buffer);
}
#if defined(WIN32) || defined(_WIN32_WCE)
#if _MSC_VER >= 1300
inline void *operator new[](size_t numbytes, jrtplib::RTPMemoryManager *mgr, int memtype)
{
if (mgr == 0)
return operator new[](numbytes);
return mgr->AllocateBuffer(numbytes,memtype);
}
inline void operator delete[](void *buffer, jrtplib::RTPMemoryManager *mgr, int memtype)
{
if (mgr == 0)
operator delete[](buffer);
else
mgr->FreeBuffer(buffer);
}
#endif // _MSC_VER >= 1300
#else
inline void *operator new[](size_t numbytes, jrtplib::RTPMemoryManager *mgr, int memtype)
{
if (mgr == 0)
return operator new[](numbytes);
return mgr->AllocateBuffer(numbytes,memtype);
}
inline void operator delete[](void *buffer, jrtplib::RTPMemoryManager *mgr, int memtype)
{
if (mgr == 0)
operator delete[](buffer);
else
mgr->FreeBuffer(buffer);
}
#endif // WIN32 || _WIN32_WCE
namespace jrtplib
{
inline void RTPDeleteByteArray(uint8_t *buf, RTPMemoryManager *mgr)
{
if (mgr == 0)
delete [] buf;
else
mgr->FreeBuffer(buf);
}
template<class ClassName>
inline void RTPDelete(ClassName *obj, RTPMemoryManager *mgr)
{
if (mgr == 0)
delete obj;
else
{
obj->~ClassName();
mgr->FreeBuffer(obj);
}
}
} // end namespace
#define RTPNew(a,b) new(a,b)
#else
#define RTPNew(a,b) new
#define RTPDelete(a,b) delete a
#define RTPDeleteByteArray(a,b) delete [] a;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
#endif // RTPMEMORYMANAGER_H

View File

@@ -0,0 +1,74 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpmemoryobject.h
*/
#ifndef RTPMEMORYOBJECT_H
#define RTPMEMORYOBJECT_H
#include "rtpconfig.h"
#include "rtpmemorymanager.h"
namespace jrtplib
{
class JRTPLIB_IMPORTEXPORT RTPMemoryObject
{
protected:
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
RTPMemoryObject(RTPMemoryManager *memmgr) : mgr(memmgr) { }
#else
RTPMemoryObject(RTPMemoryManager * /*memmgr*/) { }
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
virtual ~RTPMemoryObject() { }
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
RTPMemoryManager *GetMemoryManager() const { return mgr; }
void SetMemoryManager(RTPMemoryManager *m) { mgr = m; }
#else
RTPMemoryManager *GetMemoryManager() const { return 0; }
void SetMemoryManager(RTPMemoryManager * /*m*/) { }
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
private:
RTPMemoryManager *mgr;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
};
} // end namespace
#endif // RTPMEMORYOBJECT_H

View File

@@ -0,0 +1,358 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtppacket.h"
#include "rtpstructs.h"
#include "rtpdefines.h"
#include "rtperrors.h"
#include "rtprawpacket.h"
#if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h>
#include <string.h>
#endif // WIN32
#ifdef RTPDEBUG
#include <stdio.h>
#endif // RTPDEBUG
#include "rtpdebug.h"
namespace jrtplib
{
void RTPPacket::Clear()
{
hasextension = false;
hasmarker = false;
numcsrcs = 0;
payloadtype = 0;
extseqnr = 0;
timestamp = 0;
ssrc = 0;
packet = 0;
payload = 0;
packetlength = 0;
payloadlength = 0;
extid = 0;
extension = 0;
extensionlength = 0;
error = 0;
externalbuffer = false;
}
RTPPacket::RTPPacket(RTPRawPacket &rawpack,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(rawpack.GetReceiveTime())
{
Clear();
error = ParseRawPacket(rawpack);
}
RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs,
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
size_t maxpacksize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
{
Clear();
error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,0,maxpacksize);
}
RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs,
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
void *buffer,size_t buffersize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
{
Clear();
if (buffer == 0)
error = ERR_RTP_PACKET_EXTERNALBUFFERNULL;
else if (buffersize <= 0)
error = ERR_RTP_PACKET_ILLEGALBUFFERSIZE;
else
error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,buffer,buffersize);
}
RTPPacket::~RTPPacket()
{
if (packet && !externalbuffer)
{
RTPDeleteByteArray(packet,GetMemoryManager());
}
}
int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack)
{
uint8_t *packetbytes;
size_t packetlen;
uint8_t payloadtype;
RTPHeader *rtpheader;
bool marker;
int csrccount;
bool hasextension;
int payloadoffset,payloadlength;
int numpadbytes;
RTPExtensionHeader *rtpextheader;
uint16_t exthdrlen;
if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it
return ERR_RTP_PACKET_INVALIDPACKET;
// The length should be at least the size of the RTP header
packetlen = rawpack.GetDataLength();
if (packetlen < sizeof(RTPHeader))
return ERR_RTP_PACKET_INVALIDPACKET;
packetbytes = (uint8_t *)rawpack.GetData();
rtpheader = (RTPHeader *)packetbytes;
// The version number should be correct
if (rtpheader->version != RTP_VERSION)
return ERR_RTP_PACKET_INVALIDPACKET;
// We'll check if this is possibly a RTCP packet. For this to be possible
// the marker bit and payload type combined should be either an SR or RR
// identifier
marker = (rtpheader->marker == 0)?false:true;
payloadtype = rtpheader->payloadtype;
if (marker)
{
if (payloadtype == (RTP_RTCPTYPE_SR & 127)) // don't check high bit (this was the marker!!)
return ERR_RTP_PACKET_INVALIDPACKET;
if (payloadtype == (RTP_RTCPTYPE_RR & 127))
return ERR_RTP_PACKET_INVALIDPACKET;
}
csrccount = rtpheader->csrccount;
payloadoffset = sizeof(RTPHeader)+(int)(csrccount*sizeof(uint32_t));
if (rtpheader->padding) // adjust payload length to take padding into account
{
numpadbytes = (int)packetbytes[packetlen-1]; // last byte contains number of padding bytes
if (numpadbytes <= 0)
return ERR_RTP_PACKET_INVALIDPACKET;
}
else
numpadbytes = 0;
hasextension = (rtpheader->extension == 0)?false:true;
if (hasextension) // got header extension
{
rtpextheader = (RTPExtensionHeader *)(packetbytes+payloadoffset);
payloadoffset += sizeof(RTPExtensionHeader);
exthdrlen = ntohs(rtpextheader->length);
payloadoffset += ((int)exthdrlen)*sizeof(uint32_t);
}
else
{
rtpextheader = 0;
exthdrlen = 0;
}
payloadlength = packetlen-numpadbytes-payloadoffset;
if (payloadlength < 0)
return ERR_RTP_PACKET_INVALIDPACKET;
// Now, we've got a valid packet, so we can create a new instance of RTPPacket
// and fill in the members
RTPPacket::hasextension = hasextension;
if (hasextension)
{
RTPPacket::extid = ntohs(rtpextheader->extid);
RTPPacket::extensionlength = ((int)ntohs(rtpextheader->length))*sizeof(uint32_t);
RTPPacket::extension = ((uint8_t *)rtpextheader)+sizeof(RTPExtensionHeader);
}
RTPPacket::hasmarker = marker;
RTPPacket::numcsrcs = csrccount;
RTPPacket::payloadtype = payloadtype;
// Note: we don't fill in the EXTENDED sequence number here, since we
// don't have information about the source here. We just fill in the low
// 16 bits
RTPPacket::extseqnr = (uint32_t)ntohs(rtpheader->sequencenumber);
RTPPacket::timestamp = ntohl(rtpheader->timestamp);
RTPPacket::ssrc = ntohl(rtpheader->ssrc);
RTPPacket::packet = packetbytes;
RTPPacket::payload = packetbytes+payloadoffset;
RTPPacket::packetlength = packetlen;
RTPPacket::payloadlength = payloadlength;
// We'll zero the data of the raw packet, since we're using it here now!
rawpack.ZeroData();
return 0;
}
uint32_t RTPPacket::GetCSRC(int num) const
{
if (num >= numcsrcs)
return 0;
uint8_t *csrcpos;
uint32_t *csrcval_nbo;
uint32_t csrcval_hbo;
csrcpos = packet+sizeof(RTPHeader)+num*sizeof(uint32_t);
csrcval_nbo = (uint32_t *)csrcpos;
csrcval_hbo = ntohl(*csrcval_nbo);
return csrcval_hbo;
}
int RTPPacket::BuildPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs,
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
void *buffer,size_t maxsize)
{
if (numcsrcs > RTP_MAXCSRCS)
return ERR_RTP_PACKET_TOOMANYCSRCS;
if (payloadtype > 127) // high bit should not be used
return ERR_RTP_PACKET_BADPAYLOADTYPE;
if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types
return ERR_RTP_PACKET_BADPAYLOADTYPE;
packetlength = sizeof(RTPHeader);
packetlength += sizeof(uint32_t)*((size_t)numcsrcs);
if (gotextension)
{
packetlength += sizeof(RTPExtensionHeader);
packetlength += sizeof(uint32_t)*((size_t)extensionlen_numwords);
}
packetlength += payloadlen;
if (maxsize > 0 && packetlength > maxsize)
{
packetlength = 0;
return ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE;
}
// Ok, now we'll just fill in...
RTPHeader *rtphdr;
if (buffer == 0)
{
packet = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKET) uint8_t [packetlength];
if (packet == 0)
{
packetlength = 0;
return ERR_RTP_OUTOFMEM;
}
externalbuffer = false;
}
else
{
packet = (uint8_t *)buffer;
externalbuffer = true;
}
RTPPacket::hasmarker = gotmarker;
RTPPacket::hasextension = gotextension;
RTPPacket::numcsrcs = numcsrcs;
RTPPacket::payloadtype = payloadtype;
RTPPacket::extseqnr = (uint32_t)seqnr;
RTPPacket::timestamp = timestamp;
RTPPacket::ssrc = ssrc;
RTPPacket::payloadlength = payloadlen;
RTPPacket::extid = extensionid;
RTPPacket::extensionlength = ((size_t)extensionlen_numwords)*sizeof(uint32_t);
rtphdr = (RTPHeader *)packet;
rtphdr->version = RTP_VERSION;
rtphdr->padding = 0;
if (gotmarker)
rtphdr->marker = 1;
else
rtphdr->marker = 0;
if (gotextension)
rtphdr->extension = 1;
else
rtphdr->extension = 0;
rtphdr->csrccount = numcsrcs;
rtphdr->payloadtype = payloadtype&127; // make sure high bit isn't set
rtphdr->sequencenumber = htons(seqnr);
rtphdr->timestamp = htonl(timestamp);
rtphdr->ssrc = htonl(ssrc);
uint32_t *curcsrc;
int i;
curcsrc = (uint32_t *)(packet+sizeof(RTPHeader));
for (i = 0 ; i < numcsrcs ; i++,curcsrc++)
*curcsrc = htonl(csrcs[i]);
payload = packet+sizeof(RTPHeader)+((size_t)numcsrcs)*sizeof(uint32_t);
if (gotextension)
{
RTPExtensionHeader *rtpexthdr = (RTPExtensionHeader *)payload;
rtpexthdr->extid = htons(extensionid);
rtpexthdr->length = htons((uint16_t)extensionlen_numwords);
payload += sizeof(RTPExtensionHeader);
memcpy(payload,extensiondata,RTPPacket::extensionlength);
payload += RTPPacket::extensionlength;
}
memcpy(payload,payloaddata,payloadlen);
return 0;
}
#ifdef RTPDEBUG
void RTPPacket::Dump()
{
int i;
printf("Payload type: %d\n",(int)GetPayloadType());
printf("Extended sequence number: 0x%08x\n",GetExtendedSequenceNumber());
printf("Timestamp: 0x%08x\n",GetTimestamp());
printf("SSRC: 0x%08x\n",GetSSRC());
printf("Marker: %s\n",HasMarker()?"yes":"no");
printf("CSRC count: %d\n",GetCSRCCount());
for (i = 0 ; i < GetCSRCCount() ; i++)
printf(" CSRC[%02d]: 0x%08x\n",i,GetCSRC(i));
printf("Payload: %s\n",GetPayloadData());
printf("Payload length: %d\n",GetPayloadLength());
printf("Packet length: %d\n",GetPacketLength());
printf("Extension: %s\n",HasExtension()?"yes":"no");
if (HasExtension())
{
printf(" Extension ID: 0x%04x\n",GetExtensionID());
printf(" Extension data: %s\n",GetExtensionData());
printf(" Extension length: %d\n",GetExtensionLength());
}
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,184 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtppacket.h
*/
#ifndef RTPPACKET_H
#define RTPPACKET_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtptimeutilities.h"
#include "rtpmemoryobject.h"
namespace jrtplib
{
class RTPRawPacket;
/** Represents an RTP Packet.
* The RTPPacket class can be used to parse a RTPRawPacket instance if it represents RTP data.
* The class can also be used to create a new RTP packet according to the parameters specified by
* the user.
*/
class JRTPLIB_IMPORTEXPORT RTPPacket : public RTPMemoryObject
{
public:
/** Creates an RTPPacket instance based upon the data in \c rawpack, optionally installing a memory manager.
* Creates an RTPPacket instance based upon the data in \c rawpack, optionally installing a memory manager.
* If successful, the data is moved from the raw packet to the RTPPacket instance.
*/
RTPPacket(RTPRawPacket &rawpack,RTPMemoryManager *mgr = 0);
/** Creates a new buffer for an RTP packet and fills in the fields according to the specified parameters.
* Creates a new buffer for an RTP packet and fills in the fields according to the specified parameters.
* If \c maxpacksize is not equal to zero, an error is generated if the total packet size would exceed
* \c maxpacksize. The arguments of the constructor are self-explanatory. Note that the size of a header
* extension is specified in a number of 32-bit words. A memory manager can be installed.
*/
RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs,
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
size_t maxpacksize, RTPMemoryManager *mgr = 0);
/** This constructor is similar to the other constructor, but here data is stored in an external buffer
* \c buffer with size \c buffersize. */
RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs,
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
void *buffer,size_t buffersize,RTPMemoryManager *mgr = 0);
virtual ~RTPPacket();
/** If an error occurred in one of the constructors, this function returns the error code. */
int GetCreationError() const { return error; }
/** Returns \c true if the RTP packet has a header extension and \c false otherwise. */
bool HasExtension() const { return hasextension; }
/** Returns \c true if the marker bit was set and \c false otherwise. */
bool HasMarker() const { return hasmarker; }
/** Returns the number of CSRCs contained in this packet. */
int GetCSRCCount() const { return numcsrcs; }
/** Returns a specific CSRC identifier.
* Returns a specific CSRC identifier. The parameter \c num can go from 0 to GetCSRCCount()-1.
*/
uint32_t GetCSRC(int num) const;
/** Returns the payload type of the packet. */
uint8_t GetPayloadType() const { return payloadtype; }
/** Returns the extended sequence number of the packet.
* Returns the extended sequence number of the packet. When the packet is just received,
* only the low $16$ bits will be set. The high 16 bits can be filled in later.
*/
uint32_t GetExtendedSequenceNumber() const { return extseqnr; }
/** Returns the sequence number of this packet. */
uint16_t GetSequenceNumber() const { return (uint16_t)(extseqnr&0x0000FFFF); }
/** Sets the extended sequence number of this packet to \c seq. */
void SetExtendedSequenceNumber(uint32_t seq) { extseqnr = seq; }
/** Returns the timestamp of this packet. */
uint32_t GetTimestamp() const { return timestamp; }
/** Returns the SSRC identifier stored in this packet. */
uint32_t GetSSRC() const { return ssrc; }
/** Returns a pointer to the data of the entire packet. */
uint8_t *GetPacketData() const { return packet; }
/** Returns a pointer to the actual payload data. */
uint8_t *GetPayloadData() const { return payload; }
/** Returns the length of the entire packet. */
size_t GetPacketLength() const { return packetlength; }
/** Returns the payload length. */
size_t GetPayloadLength() const { return payloadlength; }
void SetPayloadLength(size_t l) { payloadlength = l; }
/** If a header extension is present, this function returns the extension identifier. */
uint16_t GetExtensionID() const { return extid; }
/** Returns the length of the header extension data. */
uint8_t *GetExtensionData() const { return extension; }
/** Returns the length of the header extension data. */
size_t GetExtensionLength() const { return extensionlength; }
#ifdef RTPDEBUG
void Dump();
#endif // RTPDEBUG
/** Returns the time at which this packet was received.
* When an RTPPacket instance is created from an RTPRawPacket instance, the raw packet's
* reception time is stored in the RTPPacket instance. This function then retrieves that
* time.
*/
RTPTime GetReceiveTime() const { return receivetime; }
private:
void Clear();
int ParseRawPacket(RTPRawPacket &rawpack);
int BuildPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs,
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
void *buffer,size_t maxsize);
int error;
bool hasextension,hasmarker;
int numcsrcs;
uint8_t payloadtype;
uint32_t extseqnr,timestamp,ssrc;
uint8_t *packet,*payload;
size_t packetlength,payloadlength;
uint16_t extid;
uint8_t *extension;
size_t extensionlength;
bool externalbuffer;
RTPTime receivetime;
};
} // end namespace
#endif // RTPPACKET_H

View File

@@ -0,0 +1,274 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtppacketbuilder.h"
#include "rtperrors.h"
#include "rtppacket.h"
#include "rtpsources.h"
#include <time.h>
#include <stdlib.h>
#ifdef RTPDEBUG
#include <iostream>
#endif // RTPDEBUG
#include "rtpdebug.h"
namespace jrtplib
{
RTPPacketBuilder::RTPPacketBuilder(RTPRandom &r,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),rtprnd(r),lastwallclocktime(0,0)
{
init = false;
#if (defined(WIN32) || defined(_WIN32_WCE))
timeinit.Dummy();
#endif // WIN32 || _WIN32_WCE
//std::cout << (void *)(&rtprnd) << std::endl;
}
RTPPacketBuilder::~RTPPacketBuilder()
{
Destroy();
}
int RTPPacketBuilder::Init(size_t max)
{
if (init)
return ERR_RTP_PACKBUILD_ALREADYINIT;
if (max <= 0)
return ERR_RTP_PACKBUILD_INVALIDMAXPACKETSIZE;
maxpacksize = max;
buffer = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKETBUILDERBUFFER) uint8_t [max];
if (buffer == 0)
return ERR_RTP_OUTOFMEM;
packetlength = 0;
CreateNewSSRC();
deftsset = false;
defptset = false;
defmarkset = false;
numcsrcs = 0;
init = true;
return 0;
}
void RTPPacketBuilder::Destroy()
{
if (!init)
return;
RTPDeleteByteArray(buffer,GetMemoryManager());
init = false;
}
int RTPPacketBuilder::SetMaximumPacketSize(size_t max)
{
uint8_t *newbuf;
if (max <= 0)
return ERR_RTP_PACKBUILD_INVALIDMAXPACKETSIZE;
newbuf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKETBUILDERBUFFER) uint8_t[max];
if (newbuf == 0)
return ERR_RTP_OUTOFMEM;
RTPDeleteByteArray(buffer,GetMemoryManager());
buffer = newbuf;
maxpacksize = max;
return 0;
}
int RTPPacketBuilder::AddCSRC(uint32_t csrc)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
if (numcsrcs >= RTP_MAXCSRCS)
return ERR_RTP_PACKBUILD_CSRCLISTFULL;
int i;
for (i = 0 ; i < numcsrcs ; i++)
{
if (csrcs[i] == csrc)
return ERR_RTP_PACKBUILD_CSRCALREADYINLIST;
}
csrcs[numcsrcs] = csrc;
numcsrcs++;
return 0;
}
int RTPPacketBuilder::DeleteCSRC(uint32_t csrc)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
int i = 0;
bool found = false;
while (!found && i < numcsrcs)
{
if (csrcs[i] == csrc)
found = true;
else
i++;
}
if (!found)
return ERR_RTP_PACKBUILD_CSRCNOTINLIST;
// move the last csrc in the place of the deleted one
numcsrcs--;
if (numcsrcs > 0 && numcsrcs != i)
csrcs[i] = csrcs[numcsrcs];
return 0;
}
void RTPPacketBuilder::ClearCSRCList()
{
if (!init)
return;
numcsrcs = 0;
}
uint32_t RTPPacketBuilder::CreateNewSSRC()
{
ssrc = rtprnd.GetRandom32();
timestamp = rtprnd.GetRandom32();
seqnr = rtprnd.GetRandom16() / 2;
// p 38: the count SHOULD be reset if the sender changes its SSRC identifier
numpayloadbytes = 0;
numpackets = 0;
return ssrc;
}
uint32_t RTPPacketBuilder::CreateNewSSRC(RTPSources &sources)
{
bool found;
do
{
ssrc = rtprnd.GetRandom32();
found = sources.GotEntry(ssrc);
} while (found);
timestamp = rtprnd.GetRandom32();
seqnr = rtprnd.GetRandom16() / 2;
// p 38: the count SHOULD be reset if the sender changes its SSRC identifier
numpayloadbytes = 0;
numpackets = 0;
return ssrc;
}
int RTPPacketBuilder::BuildPacket(const void *data,size_t len)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
if (!defptset)
return ERR_RTP_PACKBUILD_DEFAULTPAYLOADTYPENOTSET;
if (!defmarkset)
return ERR_RTP_PACKBUILD_DEFAULTMARKNOTSET;
if (!deftsset)
return ERR_RTP_PACKBUILD_DEFAULTTSINCNOTSET;
return PrivateBuildPacket(data,len,defaultpayloadtype,defaultmark,defaulttimestampinc,false);
}
int RTPPacketBuilder::BuildPacket(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
return PrivateBuildPacket(data,len,pt,mark,timestampinc,false);
}
int RTPPacketBuilder::BuildPacketEx(const void *data,size_t len,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
if (!defptset)
return ERR_RTP_PACKBUILD_DEFAULTPAYLOADTYPENOTSET;
if (!defmarkset)
return ERR_RTP_PACKBUILD_DEFAULTMARKNOTSET;
if (!deftsset)
return ERR_RTP_PACKBUILD_DEFAULTTSINCNOTSET;
return PrivateBuildPacket(data,len,defaultpayloadtype,defaultmark,defaulttimestampinc,true,hdrextID,hdrextdata,numhdrextwords);
}
int RTPPacketBuilder::BuildPacketEx(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
return PrivateBuildPacket(data,len,pt,mark,timestampinc,true,hdrextID,hdrextdata,numhdrextwords);
}
int RTPPacketBuilder::PrivateBuildPacket(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc,bool gotextension,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords)
{
RTPPacket p(pt,data,len,seqnr,timestamp,ssrc,mark,numcsrcs,csrcs,gotextension,hdrextID,
(uint16_t)numhdrextwords,hdrextdata,buffer,maxpacksize,GetMemoryManager());
int status = p.GetCreationError();
if (status < 0)
return status;
packetlength = p.GetPacketLength();
if (numpackets == 0) // first packet
{
lastwallclocktime = RTPTime::CurrentTime();
lastrtptimestamp = timestamp;
prevrtptimestamp = timestamp;
}
else if (timestamp != prevrtptimestamp)
{
lastwallclocktime = RTPTime::CurrentTime();
lastrtptimestamp = timestamp;
prevrtptimestamp = timestamp;
}
numpayloadbytes += (uint32_t)p.GetPayloadLength();
numpackets++;
timestamp += timestampinc;
seqnr++;
return 0;
}
} // end namespace

View File

@@ -0,0 +1,274 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtppacketbuilder.h
*/
#ifndef RTPPACKETBUILDER_H
#define RTPPACKETBUILDER_H
#include "rtpconfig.h"
#include "rtperrors.h"
#include "rtpdefines.h"
#include "rtprandom.h"
#include "rtptimeutilities.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
namespace jrtplib
{
class RTPSources;
/** This class can be used to build RTP packets and is a bit more high-level than the RTPPacket
* class: it generates an SSRC identifier, keeps track of timestamp and sequence number etc.
*/
class JRTPLIB_IMPORTEXPORT RTPPacketBuilder : public RTPMemoryObject
{
public:
/** Constructs an instance which will use \c rtprand for generating random numbers
* (used to initialize the SSRC value and sequence number), optionally installing a memory manager.
**/
RTPPacketBuilder(RTPRandom &rtprand, RTPMemoryManager *mgr = 0);
~RTPPacketBuilder();
/** Initializes the builder to only allow packets with a size below \c maxpacksize. */
int Init(size_t maxpacksize);
/** Cleans up the builder. */
void Destroy();
/** Returns the number of packets which have been created with the current SSRC identifier. */
uint32_t GetPacketCount() { if (!init) return 0; return numpackets; }
/** Returns the number of payload octets which have been generated with this SSRC identifier. */
uint32_t GetPayloadOctetCount() { if (!init) return 0; return numpayloadbytes; }
/** Sets the maximum allowed packet size to \c maxpacksize. */
int SetMaximumPacketSize(size_t maxpacksize);
/** Adds a CSRC to the CSRC list which will be stored in the RTP packets. */
int AddCSRC(uint32_t csrc);
/** Deletes a CSRC from the list which will be stored in the RTP packets. */
int DeleteCSRC(uint32_t csrc);
/** Clears the CSRC list. */
void ClearCSRCList();
/** Builds a packet with payload \c data and payload length \c len.
* Builds a packet with payload \c data and payload length \c len. The payload type, marker
* and timestamp increment used will be those that have been set using the \c SetDefault
* functions below.
*/
int BuildPacket(const void *data,size_t len);
/** Builds a packet with payload \c data and payload length \c len.
* Builds a packet with payload \c data and payload length \c len. The payload type will be
* set to \c pt, the marker bit to \c mark and after building this packet, the timestamp will
* be incremented with \c timestamp.
*/
int BuildPacket(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc);
/** Builds a packet with payload \c data and payload length \c len.
* Builds a packet with payload \c data and payload length \c len. The payload type, marker
* and timestamp increment used will be those that have been set using the \c SetDefault
* functions below. This packet will also contain an RTP header extension with identifier
* \c hdrextID and data \c hdrextdata. The length of the header extension data is given by
* \c numhdrextwords which expresses the length in a number of 32-bit words.
*/
int BuildPacketEx(const void *data,size_t len,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords);
/** Builds a packet with payload \c data and payload length \c len.
* Builds a packet with payload \c data and payload length \c len. The payload type will be set
* to \c pt, the marker bit to \c mark and after building this packet, the timestamp will
* be incremented with \c timestamp. This packet will also contain an RTP header extension
* with identifier \c hdrextID and data \c hdrextdata. The length of the header extension
* data is given by \c numhdrextwords which expresses the length in a number of 32-bit words.
*/
int BuildPacketEx(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords);
/** Returns a pointer to the last built RTP packet data. */
uint8_t *GetPacket() { if (!init) return 0; return buffer; }
/** Returns the size of the last built RTP packet. */
size_t GetPacketLength() { if (!init) return 0; return packetlength; }
/** Sets the default payload type to \c pt. */
int SetDefaultPayloadType(uint8_t pt);
/** Sets the default marker bit to \c m. */
int SetDefaultMark(bool m);
/** Sets the default timestamp increment to \c timestampinc. */
int SetDefaultTimestampIncrement(uint32_t timestampinc);
/** This function increments the timestamp with the amount given by \c inc.
* This function increments the timestamp with the amount given by \c inc. This can be useful
* if, for example, a packet was not sent because it contained only silence. Then, this function
* should be called to increment the timestamp with the appropriate amount so that the next packets
* will still be played at the correct time at other hosts.
*/
int IncrementTimestamp(uint32_t inc);
/** This function increments the timestamp with the amount given set by the SetDefaultTimestampIncrement
* member function.
* This function increments the timestamp with the amount given set by the SetDefaultTimestampIncrement
* member function. This can be useful if, for example, a packet was not sent because it contained only silence.
* Then, this function should be called to increment the timestamp with the appropriate amount so that the next
* packets will still be played at the correct time at other hosts.
*/
int IncrementTimestampDefault();
/** Creates a new SSRC to be used in generated packets.
* Creates a new SSRC to be used in generated packets. This will also generate new timestamp and
* sequence number offsets.
*/
uint32_t CreateNewSSRC();
/** Creates a new SSRC to be used in generated packets.
* Creates a new SSRC to be used in generated packets. This will also generate new timestamp and
* sequence number offsets. The source table \c sources is used to make sure that the chosen SSRC
* isn't used by another participant yet.
*/
uint32_t CreateNewSSRC(RTPSources &sources);
/** Returns the current SSRC identifier. */
uint32_t GetSSRC() const { if (!init) return 0; return ssrc; }
/** Returns the current RTP timestamp. */
uint32_t GetTimestamp() const { if (!init) return 0; return timestamp; }
/** Returns the current sequence number. */
uint16_t GetSequenceNumber() const { if (!init) return 0; return seqnr; }
/** Returns the time at which a packet was generated.
* Returns the time at which a packet was generated. This is not necessarily the time at which
* the last RTP packet was generated: if the timestamp increment was zero, the time is not updated.
*/
RTPTime GetPacketTime() const { if (!init) return RTPTime(0,0); return lastwallclocktime; }
/** Returns the RTP timestamp which corresponds to the time returned by the previous function. */
uint32_t GetPacketTimestamp() const { if (!init) return 0; return lastrtptimestamp; }
/** Sets a specific SSRC to be used.
* Sets a specific SSRC to be used. Does not create a new timestamp offset or sequence number
* offset. Does not reset the packet count or byte count. Think twice before using this!
*/
void AdjustSSRC(uint32_t s) { ssrc = s; }
private:
int PrivateBuildPacket(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc,bool gotextension,
uint16_t hdrextID = 0,const void *hdrextdata = 0,size_t numhdrextwords = 0);
RTPRandom &rtprnd;
size_t maxpacksize;
uint8_t *buffer;
size_t packetlength;
uint32_t numpayloadbytes;
uint32_t numpackets;
bool init;
uint32_t ssrc;
uint32_t timestamp;
uint16_t seqnr;
uint32_t defaulttimestampinc;
uint8_t defaultpayloadtype;
bool defaultmark;
bool deftsset,defptset,defmarkset;
uint32_t csrcs[RTP_MAXCSRCS];
int numcsrcs;
RTPTime lastwallclocktime;
uint32_t lastrtptimestamp;
uint32_t prevrtptimestamp;
};
inline int RTPPacketBuilder::SetDefaultPayloadType(uint8_t pt)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
defptset = true;
defaultpayloadtype = pt;
return 0;
}
inline int RTPPacketBuilder::SetDefaultMark(bool m)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
defmarkset = true;
defaultmark = m;
return 0;
}
inline int RTPPacketBuilder::SetDefaultTimestampIncrement(uint32_t timestampinc)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
deftsset = true;
defaulttimestampinc = timestampinc;
return 0;
}
inline int RTPPacketBuilder::IncrementTimestamp(uint32_t inc)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
timestamp += inc;
return 0;
}
inline int RTPPacketBuilder::IncrementTimestampDefault()
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
if (!deftsset)
return ERR_RTP_PACKBUILD_DEFAULTTSINCNOTSET;
timestamp += defaulttimestampinc;
return 0;
}
} // end namespace
#endif // RTPPACKETBUILDER_H

View File

@@ -0,0 +1,180 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtppollthread.h"
#ifdef RTP_SUPPORT_THREAD
#include "rtpsession.h"
#include "rtcpscheduler.h"
#include "rtperrors.h"
#include "rtprawpacket.h"
#include <time.h>
#ifndef _WIN32_WCE
#include <iostream>
#endif // _WIN32_WCE
#include "rtpdebug.h"
namespace jrtplib
{
RTPPollThread::RTPPollThread(RTPSession &session,RTCPScheduler &sched):rtpsession(session),rtcpsched(sched)
{
stop = false;
transmitter = 0;
#if (defined(WIN32) || defined(_WIN32_WCE))
timeinit.Dummy();
#endif // WIN32 || _WIN32_WCE
}
RTPPollThread::~RTPPollThread()
{
Stop();
}
int RTPPollThread::Start(RTPTransmitter *trans)
{
if (JThread::IsRunning())
return ERR_RTP_POLLTHREAD_ALREADYRUNNING;
transmitter = trans;
if (!stopmutex.IsInitialized())
{
if (stopmutex.Init() < 0)
return ERR_RTP_POLLTHREAD_CANTINITMUTEX;
}
stop = false;
if (JThread::Start() < 0)
return ERR_RTP_POLLTHREAD_CANTSTARTTHREAD;
return 0;
}
void RTPPollThread::Stop()
{
if (!IsRunning())
return;
stopmutex.Lock();
stop = true;
stopmutex.Unlock();
if (transmitter)
transmitter->AbortWait();
RTPTime thetime = RTPTime::CurrentTime();
bool done = false;
while (JThread::IsRunning() && !done)
{
// wait max 5 sec
RTPTime curtime = RTPTime::CurrentTime();
if ((curtime.GetDouble()-thetime.GetDouble()) > 5.0)
done = true;
RTPTime::Wait(RTPTime(0,10000));
}
if (JThread::IsRunning())
{
#ifndef _WIN32_WCE
std::cerr << "RTPPollThread: Warning! Having to kill thread!" << std::endl;
#endif // _WIN32_WCE
JThread::Kill();
}
stop = false;
transmitter = 0;
}
void *RTPPollThread::Thread()
{
JThread::ThreadStarted();
bool stopthread;
stopmutex.Lock();
stopthread = stop;
stopmutex.Unlock();
rtpsession.OnPollThreadStart(stopthread);
while (!stopthread)
{
int status;
rtpsession.schedmutex.Lock();
rtpsession.sourcesmutex.Lock();
RTPTime rtcpdelay = rtcpsched.GetTransmissionDelay();
rtpsession.sourcesmutex.Unlock();
rtpsession.schedmutex.Unlock();
if ((status = transmitter->WaitForIncomingData(rtcpdelay)) < 0)
{
stopthread = true;
rtpsession.OnPollThreadError(status);
}
else
{
if ((status = transmitter->Poll()) < 0)
{
stopthread = true;
rtpsession.OnPollThreadError(status);
}
else
{
if ((status = rtpsession.ProcessPolledData()) < 0)
{
stopthread = true;
rtpsession.OnPollThreadError(status);
}
else
{
rtpsession.OnPollThreadStep();
stopmutex.Lock();
stopthread = stop;
stopmutex.Unlock();
}
}
}
}
rtpsession.OnPollThreadStop();
return 0;
}
} // end namespace
#endif // RTP_SUPPORT_THREAD

View File

@@ -0,0 +1,79 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtppollthread.h
*/
#ifndef RTPPOLLTHREAD_H
#define RTPPOLLTHREAD_H
#include "rtpconfig.h"
#ifdef RTP_SUPPORT_THREAD
#include "rtptransmitter.h"
#include <jthread/jthread.h>
#include <jthread/jmutex.h>
#include <list>
namespace jrtplib
{
class RTPSession;
class RTCPScheduler;
class JRTPLIB_IMPORTEXPORT RTPPollThread : private jthread::JThread
{
public:
RTPPollThread(RTPSession &session,RTCPScheduler &rtcpsched);
~RTPPollThread();
int Start(RTPTransmitter *trans);
void Stop();
private:
void *Thread();
bool stop;
jthread::JMutex stopmutex;
RTPTransmitter *transmitter;
RTPSession &rtpsession;
RTCPScheduler &rtcpsched;
};
} // end namespace
#endif // RTP_SUPPORT_THREAD
#endif // RTPPOLLTHREAD_H

View File

@@ -0,0 +1,86 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#if defined(WIN32) && !defined(_WIN32_WCE)
#define _CRT_RAND_S
#endif // WIN32 || _WIN32_WCE
#include "rtprandom.h"
#include <time.h>
#ifndef WIN32
#include <unistd.h>
#else
#ifndef _WIN32_WCE
#include <process.h>
#else
#include <windows.h>
#include <kfuncs.h>
#endif // _WIN32_WINCE
#include <stdlib.h>
#endif // WIN32
#include "rtpdebug.h"
namespace jrtplib
{
uint32_t RTPRandom::PickSeed()
{
uint32_t x;
#if defined(WIN32) || defined(_WIN32_WINCE)
#ifndef _WIN32_WCE
x = (uint32_t)_getpid();
x += (uint32_t)time(0);
x += (uint32_t)clock();
#else
x = (uint32_t)GetCurrentProcessId();
FILETIME ft;
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st,&ft);
x += ft.dwLowDateTime;
#endif // _WIN32_WCE
x ^= (uint32_t)((uint8_t *)this - (uint8_t *)0);
#else
x = (uint32_t)getpid();
x += (uint32_t)time(0);
x += (uint32_t)clock();
x ^= (uint32_t)((uint8_t *)this - (uint8_t *)0);
#endif
return x;
}
} // end namespace

View File

@@ -0,0 +1,76 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtprandom.h
*/
#ifndef RTPRANDOM_H
#define RTPRANDOM_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include <stdlib.h>
#define RTPRANDOM_2POWMIN63 1.08420217248550443400745280086994171142578125e-19
namespace jrtplib
{
/** Interface for generating random numbers. */
class JRTPLIB_IMPORTEXPORT RTPRandom
{
public:
RTPRandom() { }
virtual ~RTPRandom() { }
/** Returns a random eight bit value. */
virtual uint8_t GetRandom8() = 0;
/** Returns a random sixteen bit value. */
virtual uint16_t GetRandom16() = 0;
/** Returns a random thirty-two bit value. */
virtual uint32_t GetRandom32() = 0;
/** Returns a random number between $0.0$ and $1.0$. */
virtual double GetRandomDouble() = 0;
/** Can be used by subclasses to generate a seed for a random number generator. */
uint32_t PickSeed();
};
} // end namespace
#endif // RTPRANDOM_H

View File

@@ -0,0 +1,125 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtprandomrand48.h"
namespace jrtplib
{
RTPRandomRand48::RTPRandomRand48()
{
SetSeed(PickSeed());
}
RTPRandomRand48::RTPRandomRand48(uint32_t seed)
{
SetSeed(seed);
}
RTPRandomRand48::~RTPRandomRand48()
{
}
void RTPRandomRand48::SetSeed(uint32_t seed)
{
#ifdef RTP_SUPPORT_THREAD
mutex.Init(); // TODO: check error!
#endif // RTP_SUPPORT_THREAD
#if (defined(WIN32) || defined(_WIN32_WCE)) && defined(_MSC_VER) && _MSC_VER <= 1200
state = ((uint64_t)seed) << 16 | 0x330Eui64;
#else
state = ((uint64_t)seed) << 16 | 0x330EULL;
#endif
}
uint8_t RTPRandomRand48::GetRandom8()
{
uint32_t x = ((GetRandom32() >> 24)&0xff);
return (uint8_t)x;
}
uint16_t RTPRandomRand48::GetRandom16()
{
uint32_t x = ((GetRandom32() >> 16)&0xffff);
return (uint16_t)x;
}
uint32_t RTPRandomRand48::GetRandom32()
{
#ifdef RTP_SUPPORT_THREAD
mutex.Lock();
#endif // RTP_SUPPORT_THREAD
#if (defined(WIN32) || defined(_WIN32_WCE)) && defined(_MSC_VER) && _MSC_VER <= 1200
state = ((0x5DEECE66Dui64*state) + 0xBui64)&0x0000ffffffffffffui64;
uint32_t x = (uint32_t)((state>>16)&0xffffffffui64);
#else
state = ((0x5DEECE66DULL*state) + 0xBULL)&0x0000ffffffffffffULL;
uint32_t x = (uint32_t)((state>>16)&0xffffffffULL);
#endif
#ifdef RTP_SUPPORT_THREAD
mutex.Unlock();
#endif // RTP_SUPPORT_THREAD
return x;
}
double RTPRandomRand48::GetRandomDouble()
{
#ifdef RTP_SUPPORT_THREAD
mutex.Lock();
#endif // RTP_SUPPORT_THREAD
#if (defined(WIN32) || defined(_WIN32_WCE)) && defined(_MSC_VER) && _MSC_VER <= 1200
state = ((0x5DEECE66Dui64*state) + 0xBui64)&0x0000ffffffffffffui64;
int64_t x = (int64_t)state;
#else
state = ((0x5DEECE66DULL*state) + 0xBULL)&0x0000ffffffffffffULL;
int64_t x = (int64_t)state;
#endif
#ifdef RTP_SUPPORT_THREAD
mutex.Unlock();
#endif // RTP_SUPPORT_THREAD
double y = 3.552713678800500929355621337890625e-15 * (double)x;
return y;
}
} // end namespace

View File

@@ -0,0 +1,75 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtprandomrand48.h
*/
#ifndef RTPRANDOMRAND48_H
#define RTPRANDOMRAND48_H
#include "rtpconfig.h"
#include "rtprandom.h"
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jmutex.h>
#endif // RTP_SUPPORT_THREAD
#include <stdio.h>
namespace jrtplib
{
/** A random number generator using the algorithm of the rand48 set of functions. */
class JRTPLIB_IMPORTEXPORT RTPRandomRand48 : public RTPRandom
{
public:
RTPRandomRand48();
RTPRandomRand48(uint32_t seed);
~RTPRandomRand48();
uint8_t GetRandom8();
uint16_t GetRandom16();
uint32_t GetRandom32();
double GetRandomDouble();
private:
void SetSeed(uint32_t seed);
#ifdef RTP_SUPPORT_THREAD
jthread::JMutex mutex;
#endif // RTP_SUPPORT_THREAD
uint64_t state;
};
} // end namespace
#endif // RTPRANDOMRAND48_H

View File

@@ -0,0 +1,200 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#if defined(WIN32) && !defined(_WIN32_WCE)
#define _CRT_RAND_S
#endif // WIN32 || _WIN32_WCE
#include "rtprandomrands.h"
#include "rtperrors.h"
#if (defined(WIN32) && !defined(_WIN32_WCE)) && (defined(_MSC_VER) && _MSC_VER >= 1400 )
#include <math.h>
#include <stdlib.h>
// If compiling on VC 8 or later for full Windows, we'll attempt to use rand_s,
// which generates better random numbers. However, its only supported on Windows XP,
// Windows Server 2003, and later, so we'll do a run-time check to see if we can
// use it (it won't work on Windows 2000 SP4 for example).
#define RTP_SUPPORT_RANDS
#endif
#include "rtpdebug.h"
namespace jrtplib
{
#ifndef RTP_SUPPORT_RANDS
RTPRandomRandS::RTPRandomRandS()
{
initialized = false;
}
RTPRandomRandS::~RTPRandomRandS()
{
}
int RTPRandomRandS::Init()
{
return ERR_RTP_RTPRANDOMRANDS_NOTSUPPORTED;
}
uint8_t RTPRandomRandS::GetRandom8()
{
return 0;
}
uint16_t RTPRandomRandS::GetRandom16()
{
return 0;
}
uint32_t RTPRandomRandS::GetRandom32()
{
return 0;
}
double RTPRandomRandS::GetRandomDouble()
{
return 0;
}
#else
RTPRandomRandS::RTPRandomRandS()
{
initialized = false;
}
RTPRandomRandS::~RTPRandomRandS()
{
}
int RTPRandomRandS::Init()
{
if (initialized) // doesn't matter then
return 0;
HMODULE hAdvApi32 = LoadLibrary(TEXT("ADVAPI32.DLL"));
if(hAdvApi32 != NULL)
{
if(NULL != GetProcAddress( hAdvApi32, "SystemFunction036" )) // RtlGenRandom
{
initialized = true;
}
FreeLibrary(hAdvApi32);
hAdvApi32 = NULL;
}
if (!initialized)
return ERR_RTP_RTPRANDOMRANDS_NOTSUPPORTED;
return 0;
}
// rand_s gives a number between 0 and UINT_MAX. We'll assume that UINT_MAX is at least 8 bits
uint8_t RTPRandomRandS::GetRandom8()
{
if (!initialized)
return 0;
unsigned int r;
rand_s(&r);
return (uint8_t)(r&0xff);
}
uint16_t RTPRandomRandS::GetRandom16()
{
if (!initialized)
return 0;
unsigned int r;
int shift = 0;
uint16_t x = 0;
for (int i = 0 ; i < 2 ; i++, shift += 8)
{
rand_s(&r);
x ^= ((uint16_t)r << shift);
}
return x;
}
uint32_t RTPRandomRandS::GetRandom32()
{
if (!initialized)
return 0;
unsigned int r;
int shift = 0;
uint32_t x = 0;
for (int i = 0 ; i < 4 ; i++, shift += 8)
{
rand_s(&r);
x ^= ((uint32_t)r << shift);
}
return x;
}
double RTPRandomRandS::GetRandomDouble()
{
if (!initialized)
return 0;
unsigned int r;
int shift = 0;
uint64_t x = 0;
for (int i = 0 ; i < 8 ; i++, shift += 8)
{
rand_s(&r);
x ^= ((uint64_t)r << shift);
}
x &= 0x7fffffffffffffffULL;
int64_t x2 = (int64_t)x;
return RTPRANDOM_2POWMIN63*(double)x2;
}
#endif // RTP_SUPPORT_RANDS
} // end namespace

View File

@@ -0,0 +1,70 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtprandomrands.h
*/
#ifndef RTPRANDOMRANDS_H
#define RTPRANDOMRANDS_H
#include "rtpconfig.h"
#include "rtprandom.h"
namespace jrtplib
{
/** A random number generator which tries to use the \c rand_s function on the
* Win32 platform.
*/
class JRTPLIB_IMPORTEXPORT RTPRandomRandS : public RTPRandom
{
public:
RTPRandomRandS();
~RTPRandomRandS();
/** Initialize the random number generator. */
int Init();
uint8_t GetRandom8();
uint16_t GetRandom16();
uint32_t GetRandom32();
double GetRandomDouble();
private:
bool initialized;
};
} // end namespace
#endif // RTPRANDOMRANDS_H

View File

@@ -0,0 +1,123 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtprandomurandom.h"
#include "rtperrors.h"
#include "rtpdebug.h"
namespace jrtplib
{
RTPRandomURandom::RTPRandomURandom()
{
device = 0;
}
RTPRandomURandom::~RTPRandomURandom()
{
if (device)
fclose(device);
}
int RTPRandomURandom::Init()
{
if (device)
return ERR_RTP_RTPRANDOMURANDOM_ALREADYOPEN;
device = fopen("/dev/urandom","rb");
if (device == 0)
return ERR_RTP_RTPRANDOMURANDOM_CANTOPEN;
return 0;
}
uint8_t RTPRandomURandom::GetRandom8()
{
if (!device)
return 0;
uint8_t value;
fread(&value, sizeof(uint8_t), 1, device);
return value;
}
uint16_t RTPRandomURandom::GetRandom16()
{
if (!device)
return 0;
uint16_t value;
fread(&value, sizeof(uint16_t), 1, device);
return value;
}
uint32_t RTPRandomURandom::GetRandom32()
{
if (!device)
return 0;
uint32_t value;
fread(&value, sizeof(uint32_t), 1, device);
return value;
}
double RTPRandomURandom::GetRandomDouble()
{
if (!device)
return 0;
uint64_t value;
fread(&value, sizeof(uint64_t), 1, device);
#if (defined(WIN32) || defined(_WIN32_WCE)) && defined(_MSC_VER) && _MSC_VER <= 1200
value &= 0x7fffffffffffffffui64;
#else
value &= 0x7fffffffffffffffULL;
#endif
int64_t value2 = (int64_t)value;
double x = RTPRANDOM_2POWMIN63*(double)value2;
return x;
}
} // end namespace

View File

@@ -0,0 +1,68 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtprandomurandom.h
*/
#ifndef RTPRANDOMURANDOM_H
#define RTPRANDOMURANDOM_H
#include "rtpconfig.h"
#include "rtprandom.h"
#include <stdio.h>
namespace jrtplib
{
/** A random number generator which uses bytes delivered by the /dev/urandom device. */
class JRTPLIB_IMPORTEXPORT RTPRandomURandom : public RTPRandom
{
public:
RTPRandomURandom();
~RTPRandomURandom();
/** Initialize the random number generator. */
int Init();
uint8_t GetRandom8();
uint16_t GetRandom16();
uint32_t GetRandom32();
double GetRandomDouble();
private:
FILE *device;
};
} // end namespace
#endif // RTPRANDOMURANDOM_H

View File

@@ -0,0 +1,114 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtprawpacket.h
*/
#ifndef RTPRAWPACKET_H
#define RTPRAWPACKET_H
#include "rtpconfig.h"
#include "rtptimeutilities.h"
#include "rtpaddress.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
namespace jrtplib
{
/** This class is used by the transmission component to store the incoming RTP and RTCP data in. */
class JRTPLIB_IMPORTEXPORT RTPRawPacket : public RTPMemoryObject
{
public:
/** Creates an instance which stores data from \c data with length \c datalen.
* Creates an instance which stores data from \c data with length \c datalen. Only the pointer
* to the data is stored, no actual copy is made! The address from which this packet originated
* is set to \c address and the time at which the packet was received is set to \c recvtime.
* The flag which indicates whether this data is RTP or RTCP data is set to \c rtp. A memory
* manager can be installed as well.
*/
RTPRawPacket(uint8_t *data,size_t datalen,RTPAddress *address,RTPTime &recvtime,bool rtp,RTPMemoryManager *mgr = 0);
~RTPRawPacket();
/** Returns the pointer to the data which is contained in this packet. */
uint8_t *GetData() { return packetdata; }
/** Returns the length of the packet described by this instance. */
size_t GetDataLength() const { return packetdatalength; }
/** Returns the time at which this packet was received. */
RTPTime GetReceiveTime() const { return receivetime; }
/** Returns the address stored in this packet. */
const RTPAddress *GetSenderAddress() const { return senderaddress; }
/** Returns \c true if this data is RTP data, \c false if it is RTCP data. */
bool IsRTP() const { return isrtp; }
/** Sets the pointer to the data stored in this packet to zero.
* Sets the pointer to the data stored in this packet to zero. This will prevent
* a \c delete call for the actual data when the destructor of RTPRawPacket is called.
* This function is used by the RTPPacket and RTCPCompoundPacket classes to obtain
* the packet data (without having to copy it) and to make sure the data isn't deleted
* when the destructor of RTPRawPacket is called.
*/
void ZeroData() { packetdata = 0; packetdatalength = 0; }
private:
uint8_t *packetdata;
size_t packetdatalength;
RTPTime receivetime;
RTPAddress *senderaddress;
bool isrtp;
};
inline RTPRawPacket::RTPRawPacket(uint8_t *data,size_t datalen,RTPAddress *address,RTPTime &recvtime,bool rtp,RTPMemoryManager *mgr):RTPMemoryObject(mgr),receivetime(recvtime)
{
packetdata = data;
packetdatalength = datalen;
senderaddress = address;
isrtp = rtp;
}
inline RTPRawPacket::~RTPRawPacket()
{
if (packetdata)
RTPDeleteByteArray(packetdata,GetMemoryManager());
if (senderaddress)
RTPDelete(senderaddress,GetMemoryManager());
}
} // end namespace
#endif // RTPRAWPACKET_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,580 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsession.h
*/
#ifndef RTPSESSION_H
#define RTPSESSION_H
#include "rtpconfig.h"
#include "rtplibraryversion.h"
#include "rtppacketbuilder.h"
#include "rtpsessionsources.h"
#include "rtptransmitter.h"
#include "rtpcollisionlist.h"
#include "rtcpscheduler.h"
#include "rtcppacketbuilder.h"
#include "rtptimeutilities.h"
#include "rtcpcompoundpacketbuilder.h"
#include "rtpmemoryobject.h"
#include <list>
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jmutex.h>
#endif // RTP_SUPPORT_THREAD
namespace jrtplib
{
class RTPTransmitter;
class RTPSessionParams;
class RTPTransmissionParams;
class RTPAddress;
class RTPSourceData;
class RTPPacket;
class RTPPollThread;
class RTPTransmissionInfo;
class RTCPCompoundPacket;
class RTCPPacket;
class RTCPAPPPacket;
/** High level class for using RTP.
* For most RTP based applications, the RTPSession class will probably be the one to use. It handles
* the RTCP part completely internally, so the user can focus on sending and receiving the actual data.
* \note The RTPSession class is not meant to be thread safe. The user should use some kind of locking
* mechanism to prevent different threads from using the same RTPSession instance.
*/
class JRTPLIB_IMPORTEXPORT RTPSession : public RTPMemoryObject
{
public:
/** Constructs an RTPSession instance, optionally using a specific instance of a random
* number generator, and optionally installing a memory manager.
* Constructs an RTPSession instance, optionally using a specific instance of a random
* number generator, and optionally installing a memory manager. If no random number generator
* is specified, the RTPSession object will try to use either a RTPRandomURandom or
* RTPRandomRandS instance. If neither is available on the current platform, a RTPRandomRand48
* instance will be used instead. By specifying a random number generator yourself, it is
* possible to use the same generator in several RTPSession instances.
*/
RTPSession(RTPRandom *rnd = 0, RTPMemoryManager *mgr = 0);
virtual ~RTPSession();
/** Creates an RTP session.
* This function creates an RTP session with parameters \c sessparams, which will use a transmitter
* corresponding to \c proto. Parameters for this transmitter can be specified as well. If \c
* proto is of type RTPTransmitter::UserDefinedProto, the NewUserDefinedTransmitter function must
* be implemented.
*/
int Create(const RTPSessionParams &sessparams,const RTPTransmissionParams *transparams = 0, RTPTransmitter::TransmissionProtocol proto = RTPTransmitter::IPv4UDPProto);
/** Creates an RTP session using \c transmitter as transmission component.
* This function creates an RTP session with parameters \c sessparams, which will use the
* transmission component \c transmitter. Initialization and destruction of the transmitter
* will not be done by the RTPSession class if this Create function is used. This function
* can be useful if you which to reuse the transmission component in another RTPSession
* instance, once the original RTPSession isn't using the transmitter anymore.
*/
int Create(const RTPSessionParams &sessparams,RTPTransmitter *transmitter);
/** Leaves the session without sending a BYE packet. */
void Destroy();
/** Sends a BYE packet and leaves the session.
* Sends a BYE packet and leaves the session. At most a time \c maxwaittime will be waited to
* send the BYE packet. If this time expires, the session will be left without sending a BYE packet.
* The BYE packet will contain as reason for leaving \c reason with length \c reasonlength.
*/
void BYEDestroy(const RTPTime &maxwaittime,const void *reason,size_t reasonlength);
/** Returns whether the session has been created or not. */
bool IsActive();
/** Returns our own SSRC. */
uint32_t GetLocalSSRC();
/** Adds \c addr to the list of destinations. */
int AddDestination(const RTPAddress &addr);
/** Deletes \c addr from the list of destinations. */
int DeleteDestination(const RTPAddress &addr);
/** Clears the list of destinations. */
void ClearDestinations();
/** Returns \c true if multicasting is supported. */
bool SupportsMulticasting();
/** Joins the multicast group specified by \c addr. */
int JoinMulticastGroup(const RTPAddress &addr);
/** Leaves the multicast group specified by \c addr. */
int LeaveMulticastGroup(const RTPAddress &addr);
/** Leaves all multicast groups. */
void LeaveAllMulticastGroups();
/** Sends the RTP packet with payload \c data which has length \c len.
* Sends the RTP packet with payload \c data which has length \c len.
* The used payload type, marker and timestamp increment will be those that have been set
* using the \c SetDefault member functions.
*/
int SendPacket(const void *data,size_t len);
/** Sends the RTP packet with payload \c data which has length \c len.
* It will use payload type \c pt, marker \c mark and after the packet has been built, the
* timestamp will be incremented by \c timestampinc.
*/
int SendPacket(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc);
/** Sends the RTP packet with payload \c data which has length \c len.
* The packet will contain a header extension with identifier \c hdrextID and containing data
* \c hdrextdata. The length of this data is given by \c numhdrextwords and is specified in a
* number of 32-bit words. The used payload type, marker and timestamp increment will be those that
* have been set using the \c SetDefault member functions.
*/
int SendPacketEx(const void *data,size_t len,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords);
/** Sends the RTP packet with payload \c data which has length \c len.
* It will use payload type \c pt, marker \c mark and after the packet has been built, the
* timestamp will be incremented by \c timestampinc. The packet will contain a header
* extension with identifier \c hdrextID and containing data \c hdrextdata. The length
* of this data is given by \c numhdrextwords and is specified in a number of 32-bit words.
*/
int SendPacketEx(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords);
#ifdef RTP_SUPPORT_SENDAPP
/** If sending of RTCP APP packets was enabled at compile time, this function creates a compound packet
* containing an RTCP APP packet and sends it immediately.
* If sending of RTCP APP packets was enabled at compile time, this function creates a compound packet
* containing an RTCP APP packet and sends it immediately. If successful, the function returns the number
* of bytes in the RTCP compound packet. Note that this immediate sending is not compliant with the RTP
* specification, so use with care.
*/
int SendRTCPAPPPacket(uint8_t subtype, const uint8_t name[4], const void *appdata, size_t appdatalen);
#endif // RTP_SUPPORT_SENDAPP
#ifdef RTP_SUPPORT_RTCPUNKNOWN
/** Tries to send an Unknown packet immediately.
* Tries to send an Unknown packet immediately. If successful, the function returns the number
* of bytes in the RTCP compound packet. Note that this immediate sending is not compliant with the RTP
* specification, so use with care. Can send message along with a receiver report or a sender report
*/
int SendUnknownPacket(bool sr, uint8_t payload_type, uint8_t subtype, const void *data, size_t len);
#endif // RTP_SUPPORT_RTCPUNKNOWN
/** Sets the default payload type for RTP packets to \c pt. */
int SetDefaultPayloadType(uint8_t pt);
/** Sets the default marker for RTP packets to \c m. */
int SetDefaultMark(bool m);
/** Sets the default value to increment the timestamp with to \c timestampinc. */
int SetDefaultTimestampIncrement(uint32_t timestampinc);
/** This function increments the timestamp with the amount given by \c inc.
* This function increments the timestamp with the amount given by \c inc. This can be useful
* if, for example, a packet was not sent because it contained only silence. Then, this function
* should be called to increment the timestamp with the appropriate amount so that the next packets
* will still be played at the correct time at other hosts.
*/
int IncrementTimestamp(uint32_t inc);
/** This function increments the timestamp with the amount given set by the SetDefaultTimestampIncrement
* member function.
* This function increments the timestamp with the amount given set by the SetDefaultTimestampIncrement
* member function. This can be useful if, for example, a packet was not sent because it contained only silence.
* Then, this function should be called to increment the timestamp with the appropriate amount so that the next
* packets will still be played at the correct time at other hosts.
*/
int IncrementTimestampDefault();
/** This function allows you to inform the library about the delay between sampling the first
* sample of a packet and sending the packet.
* This function allows you to inform the library about the delay between sampling the first
* sample of a packet and sending the packet. This delay is taken into account when calculating the
* relation between RTP timestamp and wallclock time, used for inter-media synchronization.
*/
int SetPreTransmissionDelay(const RTPTime &delay);
/** This function returns an instance of a subclass of RTPTransmissionInfo which will give some
* additional information about the transmitter (a list of local IP addresses for example).
* This function returns an instance of a subclass of RTPTransmissionInfo which will give some
* additional information about the transmitter (a list of local IP addresses for example). The user
* has to free the returned instance when it is no longer needed, preferably using the DeleteTransmissionInfo
* function.
*/
RTPTransmissionInfo *GetTransmissionInfo();
/** Frees the memory used by the transmission information \c inf. */
void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
/** If you're not using the poll thread, this function must be called regularly to process incoming data
* and to send RTCP data when necessary.
*/
int Poll();
/** Waits at most a time \c delay until incoming data has been detected.
* Waits at most a time \c delay until incoming data has been detected. Only works when you're not
* using the poll thread. If \c dataavailable is not \c NULL, it should be set to \c true if data
* was actually read and to \c false otherwise.
*/
int WaitForIncomingData(const RTPTime &delay,bool *dataavailable = 0);
/** If the previous function has been called, this one aborts the waiting (only works when you're not
* using the poll thread).
*/
int AbortWait();
/** Returns the time interval after which an RTCP compound packet may have to be sent (only works when
* you're not using the poll thread.
*/
RTPTime GetRTCPDelay();
/** The following member functions (till EndDataAccess}) need to be accessed between a call
* to BeginDataAccess and EndDataAccess.
* The BeginDataAccess function makes sure that the poll thread won't access the source table
* at the same time that you're using it. When the EndDataAccess is called, the lock on the
* source table is freed again.
*/
int BeginDataAccess();
/** Starts the iteration over the participants by going to the first member in the table.
* Starts the iteration over the participants by going to the first member in the table.
* If a member was found, the function returns \c true, otherwise it returns \c false.
*/
bool GotoFirstSource();
/** Sets the current source to be the next source in the table.
* Sets the current source to be the next source in the table. If we're already at the last
* source, the function returns \c false, otherwise it returns \c true.
*/
bool GotoNextSource();
/** Sets the current source to be the previous source in the table.
* Sets the current source to be the previous source in the table. If we're at the first source,
* the function returns \c false, otherwise it returns \c true.
*/
bool GotoPreviousSource();
/** Sets the current source to be the first source in the table which has RTPPacket instances
* that we haven't extracted yet.
* Sets the current source to be the first source in the table which has RTPPacket instances
* that we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoFirstSourceWithData();
/** Sets the current source to be the next source in the table which has RTPPacket instances
* that we haven't extracted yet.
* Sets the current source to be the next source in the table which has RTPPacket instances
* that we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoNextSourceWithData();
/** Sets the current source to be the previous source in the table which has RTPPacket
* instances that we haven't extracted yet.
* Sets the current source to be the previous source in the table which has RTPPacket
* instances that we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoPreviousSourceWithData();
/** Returns the \c RTPSourceData instance for the currently selected participant. */
RTPSourceData *GetCurrentSourceInfo();
/** Returns the \c RTPSourceData instance for the participant identified by \c ssrc,
* or NULL if no such entry exists.
*/
RTPSourceData *GetSourceInfo(uint32_t ssrc);
/** Extracts the next packet from the received packets queue of the current participant,
* or NULL if no more packets are available.
* Extracts the next packet from the received packets queue of the current participant,
* or NULL if no more packets are available. When the packet is no longer needed, its
* memory should be freed using the DeletePacket member function.
*/
RTPPacket *GetNextPacket();
/** Frees the memory used by \c p. */
void DeletePacket(RTPPacket *p);
/** See BeginDataAccess. */
int EndDataAccess();
/** Sets the receive mode to \c m.
* Sets the receive mode to \c m. Note that when the receive mode is changed, the list of
* addresses to be ignored ot accepted will be cleared.
*/
int SetReceiveMode(RTPTransmitter::ReceiveMode m);
/** Adds \c addr to the list of addresses to ignore. */
int AddToIgnoreList(const RTPAddress &addr);
/** Deletes \c addr from the list of addresses to ignore. */
int DeleteFromIgnoreList(const RTPAddress &addr);
/** Clears the list of addresses to ignore. */
void ClearIgnoreList();
/** Adds \c addr to the list of addresses to accept. */
int AddToAcceptList(const RTPAddress &addr);
/** Deletes \c addr from the list of addresses to accept. */
int DeleteFromAcceptList(const RTPAddress &addr);
/** Clears the list of addresses to accept. */
void ClearAcceptList();
/** Sets the maximum allowed packet size to \c s. */
int SetMaximumPacketSize(size_t s);
/** Sets the session bandwidth to \c bw, which is specified in bytes per second. */
int SetSessionBandwidth(double bw);
/** Sets the timestamp unit for our own data.
* Sets the timestamp unit for our own data. The timestamp unit is defined as a time interval in
* seconds divided by the corresponding timestamp interval. For example, for 8000 Hz audio, the
* timestamp unit would typically be 1/8000. Since this value is initially set to an illegal value,
* the user must set this to an allowed value to be able to create a session.
*/
int SetTimestampUnit(double u);
/** Sets the RTCP interval for the SDES name item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES name item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetNameInterval(int count);
/** Sets the RTCP interval for the SDES e-mail item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES e-mail item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetEMailInterval(int count);
/** Sets the RTCP interval for the SDES location item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES location item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetLocationInterval(int count);
/** Sets the RTCP interval for the SDES phone item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES phone item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetPhoneInterval(int count);
/** Sets the RTCP interval for the SDES tool item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES tool item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetToolInterval(int count);
/** Sets the RTCP interval for the SDES note item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES note item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetNoteInterval(int count);
/** Sets the SDES name item for the local participant to the value \c s with length \c len. */
int SetLocalName(const void *s,size_t len);
/** Sets the SDES e-mail item for the local participant to the value \c s with length \c len. */
int SetLocalEMail(const void *s,size_t len);
/** Sets the SDES location item for the local participant to the value \c s with length \c len. */
int SetLocalLocation(const void *s,size_t len);
/** Sets the SDES phone item for the local participant to the value \c s with length \c len. */
int SetLocalPhone(const void *s,size_t len);
/** Sets the SDES tool item for the local participant to the value \c s with length \c len. */
int SetLocalTool(const void *s,size_t len);
/** Sets the SDES note item for the local participant to the value \c s with length \c len. */
int SetLocalNote(const void *s,size_t len);
#ifdef RTPDEBUG
void DumpSources();
void DumpTransmitter();
#endif // RTPDEBUG
protected:
/** Allocate a user defined transmitter.
* In case you specified in the Create function that you want to use a
* user defined transmitter, you should override this function. The RTPTransmitter
* instance returned by this function will then be used to send and receive RTP and
* RTCP packets. Note that when the session is destroyed, this RTPTransmitter
* instance will be destroyed as well.
*/
virtual RTPTransmitter *NewUserDefinedTransmitter() { return 0; }
/** Is called when an incoming RTP packet is about to be processed. */
virtual void OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress) { }
/** Is called when an incoming RTCP packet is about to be processed. */
virtual void OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress) { }
/** Is called when an SSRC collision was detected.
* Is called when an SSRC collision was detected. The instance \c srcdat is the one present in
* the table, the address \c senderaddress is the one that collided with one of the addresses
* and \c isrtp indicates against which address of \c srcdat the check failed.
*/
virtual void OnSSRCCollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp) { }
/** Is called when another CNAME was received than the one already present for source \c srcdat. */
virtual void OnCNAMECollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,
const uint8_t *cname,size_t cnamelength) { }
/** Is called when a new entry \c srcdat is added to the source table. */
virtual void OnNewSource(RTPSourceData *srcdat) { }
/** Is called when the entry \c srcdat is about to be deleted from the source table. */
virtual void OnRemoveSource(RTPSourceData *srcdat) { }
/** Is called when participant \c srcdat is timed out. */
virtual void OnTimeout(RTPSourceData *srcdat) { }
/** Is called when participant \c srcdat is timed after having sent a BYE packet. */
virtual void OnBYETimeout(RTPSourceData *srcdat) { }
/** Is called when an RTCP APP packet \c apppacket has been received at time \c receivetime
* from address \c senderaddress.
*/
virtual void OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,
const RTPAddress *senderaddress) { }
/** Is called when an unknown RTCP packet type was detected. */
virtual void OnUnknownPacketType(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress) { }
/** Is called when an unknown packet format for a known packet type was detected. */
virtual void OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress) { }
/** Is called when the SDES NOTE item for source \c srcdat has been timed out. */
virtual void OnNoteTimeout(RTPSourceData *srcdat) { }
/** Is called when a BYE packet has been processed for source \c srcdat. */
virtual void OnBYEPacket(RTPSourceData *srcdat) { }
/** Is called when an RTCP compound packet has just been sent (useful to inspect outgoing RTCP data). */
virtual void OnSendRTCPCompoundPacket(RTCPCompoundPacket *pack) { }
#ifdef RTP_SUPPORT_THREAD
/** Is called when error \c errcode was detected in the poll thread. */
virtual void OnPollThreadError(int errcode) { }
/** Is called each time the poll thread loops.
* Is called each time the poll thread loops. This happens when incoming data was
* detected or when it's time to send an RTCP compound packet.
*/
virtual void OnPollThreadStep() { }
/** Is called when the poll thread is started.
* Is called when the poll thread is started. This happens just before entering the
* thread main loop.
* \param stop This can be used to stop the thread immediately without entering the loop.
*/
virtual void OnPollThreadStart(bool &stop) { }
/** Is called when the poll thread is going to stop.
* Is called when the poll thread is going to stop. This happens just before termitating the thread.
*/
virtual void OnPollThreadStop() { }
#endif // RTP_SUPPORT_THREAD
private:
int InternalCreate(const RTPSessionParams &sessparams);
int CreateCNAME(uint8_t *buffer,size_t *bufferlength,bool resolve);
int ProcessPolledData();
int ProcessRTCPCompoundPacket(RTCPCompoundPacket &rtcpcomppack,RTPRawPacket *pack);
RTPRandom *GetRandomNumberGenerator(RTPRandom *r);
RTPRandom *rtprnd;
bool deletertprnd;
RTPTransmitter *rtptrans;
bool created;
bool deletetransmitter;
bool usingpollthread;
bool acceptownpackets;
bool useSR_BYEifpossible;
size_t maxpacksize;
double sessionbandwidth;
double controlfragment;
double sendermultiplier;
double byemultiplier;
double membermultiplier;
double collisionmultiplier;
double notemultiplier;
bool sentpackets;
RTPSessionSources sources;
RTPPacketBuilder packetbuilder;
RTCPScheduler rtcpsched;
RTCPPacketBuilder rtcpbuilder;
RTPCollisionList collisionlist;
std::list<RTCPCompoundPacket *> byepackets;
#ifdef RTP_SUPPORT_THREAD
RTPPollThread *pollthread;
jthread::JMutex sourcesmutex,buildermutex,schedmutex,packsentmutex;
friend class RTPPollThread;
#endif // RTP_SUPPORT_THREAD
friend class RTPSessionSources;
friend class RTCPSessionPacketBuilder;
};
} // end namespace
#endif // RTPSESSION_H

View File

@@ -0,0 +1,88 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpconfig.h"
#include "rtpsessionparams.h"
#include "rtpdefines.h"
#include "rtperrors.h"
#include "rtpdebug.h"
namespace jrtplib
{
RTPSessionParams::RTPSessionParams() : mininterval(0,0)
{
#ifdef RTP_SUPPORT_THREAD
usepollthread = true;
#else
usepollthread = false;
#endif // RTP_SUPPORT_THREAD
maxpacksize = RTP_DEFAULTPACKETSIZE;
receivemode = RTPTransmitter::AcceptAll;
acceptown = false;
owntsunit = -1; // The user will have to set it to the correct value himself
resolvehostname = false;
#ifdef RTP_SUPPORT_PROBATION
probationtype = RTPSources::ProbationStore;
#endif // RTP_SUPPORT_PROBATION
mininterval = RTPTime(RTCP_DEFAULTMININTERVAL);
sessionbandwidth = RTP_DEFAULTSESSIONBANDWIDTH;
controlfrac = RTCP_DEFAULTBANDWIDTHFRACTION;
senderfrac = RTCP_DEFAULTSENDERFRACTION;
usehalfatstartup = RTCP_DEFAULTHALFATSTARTUP;
immediatebye = RTCP_DEFAULTIMMEDIATEBYE;
SR_BYE = RTCP_DEFAULTSRBYE;
sendermultiplier = RTP_SENDERTIMEOUTMULTIPLIER;
generaltimeoutmultiplier = RTP_MEMBERTIMEOUTMULTIPLIER;
byetimeoutmultiplier = RTP_BYETIMEOUTMULTIPLIER;
collisionmultiplier = RTP_COLLISIONTIMEOUTMULTIPLIER;
notemultiplier = RTP_NOTETTIMEOUTMULTIPLIER;
usepredefinedssrc = false;
predefinedssrc = 0;
}
int RTPSessionParams::SetUsePollThread(bool usethread)
{
#ifndef RTP_SUPPORT_THREAD
return ERR_RTP_NOTHREADSUPPORT;
#else
usepollthread = usethread;
return 0;
#endif // RTP_SUPPORT_THREAD
}
} // end namespace

View File

@@ -0,0 +1,248 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsessionparams.h
*/
#ifndef RTPSESSIONPARAMS_H
#define RTPSESSIONPARAMS_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtptransmitter.h"
#include "rtptimeutilities.h"
#include "rtpsources.h"
namespace jrtplib
{
/** Describes the parameters for to be used by an RTPSession instance.
* Describes the parameters for to be used by an RTPSession instance. Note that the own timestamp
* unit must be set to a valid number, otherwise the session can't be created.
*/
class JRTPLIB_IMPORTEXPORT RTPSessionParams
{
public:
RTPSessionParams();
/** If \c usethread is \c true, the session will use a poll thread to automatically process incoming
* data and to send RTCP packets when necessary.
*/
int SetUsePollThread(bool usethread);
/** Returns whether the session should use a poll thread or not (default is \c true). */
bool IsUsingPollThread() const { return usepollthread; }
/** Sets the maximum allowed packet size for the session. */
void SetMaximumPacketSize(size_t max) { maxpacksize = max; }
/** Returns the maximum allowed packet size (default is 1400 bytes). */
size_t GetMaximumPacketSize() const { return maxpacksize; }
/** If the argument is \c true, the session should accept its own packets and store
* them accordingly in the source table.
*/
void SetAcceptOwnPackets(bool accept) { acceptown = accept; }
/** Returns \c true if the session should accept its own packets (default is \c false). */
bool AcceptOwnPackets() const { return acceptown; }
/** Sets the receive mode to be used by the session. */
void SetReceiveMode(RTPTransmitter::ReceiveMode recvmode) { receivemode = recvmode; }
/** Sets the receive mode to be used by the session (default is: accept all packets). */
RTPTransmitter::ReceiveMode GetReceiveMode() const { return receivemode; }
/** Sets the timestamp unit for our own data.
* Sets the timestamp unit for our own data. The timestamp unit is defined as a time interval in
* seconds divided by the corresponding timestamp interval. For example, for 8000 Hz audio, the
* timestamp unit would typically be 1/8000. Since this value is initially set to an illegal value,
* the user must set this to an allowed value to be able to create a session.
*/
void SetOwnTimestampUnit(double tsunit) { owntsunit = tsunit; }
/** Returns the currently set timestamp unit. */
double GetOwnTimestampUnit() const { return owntsunit; }
/** Sets a flag indicating if a DNS lookup should be done to determine our hostname (to construct a CNAME item).
* If \c v is set to \c true, the session will ask the transmitter to find a host name based upon the IP
* addresses in its list of local IP addresses. If set to \c false, a call to \c gethostname or something
* similar will be used to find the local hostname. Note that the first method might take some time.
*/
void SetResolveLocalHostname(bool v) { resolvehostname = v; }
/** Returns whether the local hostname should be determined from the transmitter's list of local IP addresses
* or not (default is \c false).
*/
bool GetResolveLocalHostname() const { return resolvehostname; }
#ifdef RTP_SUPPORT_PROBATION
/** If probation support is enabled, this function sets the probation type to be used. */
void SetProbationType(RTPSources::ProbationType probtype) { probationtype = probtype; }
/** Returns the probation type which will be used (default is RTPSources::ProbationStore). */
RTPSources::ProbationType GetProbationType() const { return probationtype; }
#endif // RTP_SUPPORT_PROBATION
/** Sets the session bandwidth in bytes per second. */
void SetSessionBandwidth(double sessbw) { sessionbandwidth = sessbw; }
/** Returns the session bandwidth in bytes per second (default is 10000 bytes per second). */
double GetSessionBandwidth() const { return sessionbandwidth; }
/** Sets the fraction of the session bandwidth to be used for control traffic. */
void SetControlTrafficFraction(double frac) { controlfrac = frac; }
/** Returns the fraction of the session bandwidth that will be used for control traffic (default is 5%). */
double GetControlTrafficFraction() const { return controlfrac; }
/** Sets the minimum fraction of the control traffic that will be used by senders. */
void SetSenderControlBandwidthFraction(double frac) { senderfrac = frac; }
/** Returns the minimum fraction of the control traffic that will be used by senders (default is 25%). */
double GetSenderControlBandwidthFraction() const { return senderfrac; }
/** Set the minimal time interval between sending RTCP packets. */
void SetMinimumRTCPTransmissionInterval(const RTPTime &t) { mininterval = t; }
/** Returns the minimal time interval between sending RTCP packets (default is 5 seconds). */
RTPTime GetMinimumRTCPTransmissionInterval() const { return mininterval; }
/** If \c usehalf is set to \c true, the session will only wait half of the calculated RTCP
* interval before sending its first RTCP packet.
*/
void SetUseHalfRTCPIntervalAtStartup(bool usehalf) { usehalfatstartup = usehalf; }
/** Returns whether the session will only wait half of the calculated RTCP interval before sending its
* first RTCP packet or not (default is \c true).
*/
bool GetUseHalfRTCPIntervalAtStartup() const { return usehalfatstartup; }
/** If \c v is \c true, the session will send a BYE packet immediately if this is allowed. */
void SetRequestImmediateBYE(bool v) { immediatebye = v; }
/** Returns whether the session should send a BYE packet immediately (if allowed) or not (default is \c true). */
bool GetRequestImmediateBYE() const { return immediatebye; }
/** When sending a BYE packet, this indicates whether it will be part of an RTCP compound packet
* that begins with a sender report (if allowed) or a receiver report.
*/
void SetSenderReportForBYE(bool v) { SR_BYE = v; }
/** Returns \c true if a BYE packet will be sent in an RTCP compound packet which starts with a
* sender report; if a receiver report will be used, the function returns \c false (default is \c true).
*/
bool GetSenderReportForBYE() const { return SR_BYE; }
/** Sets the multiplier to be used when timing out senders. */
void SetSenderTimeoutMultiplier(double m) { sendermultiplier = m; }
/** Returns the multiplier to be used when timing out senders (default is 2). */
double GetSenderTimeoutMultiplier() const { return sendermultiplier; }
/** Sets the multiplier to be used when timing out members. */
void SetSourceTimeoutMultiplier(double m) { generaltimeoutmultiplier = m; }
/** Returns the multiplier to be used when timing out members (default is 5). */
double GetSourceTimeoutMultiplier() const { return generaltimeoutmultiplier; }
/** Sets the multiplier to be used when timing out a member after it has sent a BYE packet. */
void SetBYETimeoutMultiplier(double m) { byetimeoutmultiplier = m; }
/** Returns the multiplier to be used when timing out a member after it has sent a BYE packet (default is 1). */
double GetBYETimeoutMultiplier() const { return byetimeoutmultiplier; }
/** Sets the multiplier to be used when timing out entries in the collision table. */
void SetCollisionTimeoutMultiplier(double m) { collisionmultiplier = m; }
/** Returns the multiplier to be used when timing out entries in the collision table (default is 10). */
double GetCollisionTimeoutMultiplier() const { return collisionmultiplier; }
/** Sets the multiplier to be used when timing out SDES NOTE information. */
void SetNoteTimeoutMultiplier(double m) { notemultiplier = m; }
/** Returns the multiplier to be used when timing out SDES NOTE information (default is 25). */
double GetNoteTimeoutMultiplier() const { return notemultiplier; }
/** Sets a flag which indicates if a predefined SSRC identifier should be used. */
void SetUsePredefinedSSRC(bool f) { usepredefinedssrc = f; }
/** Returns a flag indicating if a predefined SSRC should be used. */
bool GetUsePredefinedSSRC() const { return usepredefinedssrc; }
/** Sets the SSRC which will be used if RTPSessionParams::GetUsePredefinedSSRC returns true. */
void SetPredefinedSSRC(uint32_t ssrc) { predefinedssrc = ssrc; }
/** Returns the SSRC which will be used if RTPSessionParams::GetUsePredefinedSSRC returns true. */
uint32_t GetPredefinedSSRC() const { return predefinedssrc; }
/** Forces this string to be used as the CNAME identifier. */
void SetCNAME(const std::string &s) { cname = s; }
/** Returns the currently set CNAME, is blank when this will be generated automatically (the default). */
std::string GetCNAME() const { return cname; }
private:
bool acceptown;
bool usepollthread;
size_t maxpacksize;
double owntsunit;
RTPTransmitter::ReceiveMode receivemode;
bool resolvehostname;
#ifdef RTP_SUPPORT_PROBATION
RTPSources::ProbationType probationtype;
#endif // RTP_SUPPORT_PROBATION
double sessionbandwidth;
double controlfrac;
double senderfrac;
RTPTime mininterval;
bool usehalfatstartup;
bool immediatebye;
bool SR_BYE;
double sendermultiplier;
double generaltimeoutmultiplier;
double byetimeoutmultiplier;
double collisionmultiplier;
double notemultiplier;
bool usepredefinedssrc;
uint32_t predefinedssrc;
std::string cname;
};
} // end namespace
#endif // RTPSESSIONPARAMS_H

View File

@@ -0,0 +1,114 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpsessionsources.h"
#include "rtpsession.h"
#include "rtpsourcedata.h"
#include "rtpdebug.h"
namespace jrtplib
{
void RTPSessionSources::OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime,const RTPAddress *senderaddress)
{
rtpsession.OnRTPPacket(pack,receivetime,senderaddress);
}
void RTPSessionSources::OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,const RTPAddress *senderaddress)
{
if (senderaddress != 0) // don't analyse own RTCP packets again (they're already analysed on their way out)
rtpsession.rtcpsched.AnalyseIncoming(*pack);
rtpsession.OnRTCPCompoundPacket(pack,receivetime,senderaddress);
}
void RTPSessionSources::OnSSRCCollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp)
{
if (srcdat->IsOwnSSRC())
owncollision = true;
rtpsession.OnSSRCCollision(srcdat,senderaddress,isrtp);
}
void RTPSessionSources::OnCNAMECollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,const uint8_t *cname,size_t cnamelength)
{
rtpsession.OnCNAMECollision(srcdat,senderaddress,cname,cnamelength);
}
void RTPSessionSources::OnNewSource(RTPSourceData *srcdat)
{
rtpsession.OnNewSource(srcdat);
}
void RTPSessionSources::OnRemoveSource(RTPSourceData *srcdat)
{
rtpsession.OnRemoveSource(srcdat);
}
void RTPSessionSources::OnTimeout(RTPSourceData *srcdat)
{
rtpsession.rtcpsched.ActiveMemberDecrease();
rtpsession.OnTimeout(srcdat);
}
void RTPSessionSources::OnBYETimeout(RTPSourceData *srcdat)
{
rtpsession.OnBYETimeout(srcdat);
}
void RTPSessionSources::OnBYEPacket(RTPSourceData *srcdat)
{
rtpsession.rtcpsched.ActiveMemberDecrease();
rtpsession.OnBYEPacket(srcdat);
}
void RTPSessionSources::OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,const RTPAddress *senderaddress)
{
rtpsession.OnAPPPacket(apppacket,receivetime,senderaddress);
}
void RTPSessionSources::OnUnknownPacketType(RTCPPacket *rtcppack,const RTPTime &receivetime, const RTPAddress *senderaddress)
{
rtpsession.OnUnknownPacketType(rtcppack,receivetime,senderaddress);
}
void RTPSessionSources::OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime,const RTPAddress *senderaddress)
{
rtpsession.OnUnknownPacketFormat(rtcppack,receivetime,senderaddress);
}
void RTPSessionSources::OnNoteTimeout(RTPSourceData *srcdat)
{
rtpsession.OnNoteTimeout(srcdat);
}
} // end namespace

View File

@@ -0,0 +1,84 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsessionsources.h
*/
#ifndef RTPSESSIONSOURCES_H
#define RTPSESSIONSOURCES_H
#include "rtpconfig.h"
#include "rtpsources.h"
namespace jrtplib
{
class RTPSession;
class JRTPLIB_IMPORTEXPORT RTPSessionSources : public RTPSources
{
public:
RTPSessionSources(RTPSession &sess,RTPMemoryManager *mgr) : RTPSources(RTPSources::ProbationStore,mgr),rtpsession(sess)
{ owncollision = false; }
~RTPSessionSources() { }
void ClearOwnCollisionFlag() { owncollision = false; }
bool DetectedOwnCollision() const { return owncollision; }
private:
void OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnSSRCCollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp);
void OnCNAMECollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,
const uint8_t *cname,size_t cnamelength);
void OnNewSource(RTPSourceData *srcdat);
void OnRemoveSource(RTPSourceData *srcdat);
void OnTimeout(RTPSourceData *srcdat);
void OnBYETimeout(RTPSourceData *srcdat);
void OnBYEPacket(RTPSourceData *srcdat);
void OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnUnknownPacketType(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnNoteTimeout(RTPSourceData *srcdat);
RTPSession &rtpsession;
bool owncollision;
};
} // end namespace
#endif // RTPSESSIONSOURCES_H

View File

@@ -0,0 +1,500 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpsourcedata.h"
#include "rtpdefines.h"
#include "rtpaddress.h"
#include "rtpmemorymanager.h"
#if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h>
#endif // WIN32
#ifdef RTPDEBUG
#include <iostream>
#include <string>
#endif // RTPDEBUG
#include "rtpdebug.h"
#define ACCEPTPACKETCODE \
*accept = true; \
\
sentdata = true; \
packetsreceived++; \
numnewpackets++; \
\
if (pack->GetExtendedSequenceNumber() == 0) \
{ \
baseseqnr = 0x0000FFFF; \
numcycles = 0x00010000; \
} \
else \
baseseqnr = pack->GetExtendedSequenceNumber() - 1; \
\
exthighseqnr = baseseqnr + 1; \
prevpacktime = receivetime; \
prevexthighseqnr = baseseqnr; \
savedextseqnr = baseseqnr; \
\
pack->SetExtendedSequenceNumber(exthighseqnr); \
\
prevtimestamp = pack->GetTimestamp(); \
lastmsgtime = prevpacktime; \
if (!ownpacket) /* for own packet, this value is set on an outgoing packet */ \
lastrtptime = prevpacktime;
namespace jrtplib
{
void RTPSourceStats::ProcessPacket(RTPPacket *pack,const RTPTime &receivetime,double tsunit,
bool ownpacket,bool *accept,bool applyprobation,bool *onprobation)
{
// Note that the sequence number in the RTP packet is still just the
// 16 bit number contained in the RTP header
*onprobation = false;
if (!sentdata) // no valid packets received yet
{
#ifdef RTP_SUPPORT_PROBATION
if (applyprobation)
{
bool acceptpack = false;
if (probation)
{
uint16_t pseq;
uint32_t pseq2;
pseq = prevseqnr;
pseq++;
pseq2 = (uint32_t)pseq;
if (pseq2 == pack->GetExtendedSequenceNumber()) // ok, its the next expected packet
{
prevseqnr = (uint16_t)pack->GetExtendedSequenceNumber();
probation--;
if (probation == 0) // probation over
acceptpack = true;
else
*onprobation = true;
}
else // not next packet
{
probation = RTP_PROBATIONCOUNT;
prevseqnr = (uint16_t)pack->GetExtendedSequenceNumber();
*onprobation = true;
}
}
else // first packet received with this SSRC ID, start probation
{
probation = RTP_PROBATIONCOUNT;
prevseqnr = (uint16_t)pack->GetExtendedSequenceNumber();
*onprobation = true;
}
if (acceptpack)
{
ACCEPTPACKETCODE
}
else
{
*accept = false;
lastmsgtime = receivetime;
}
}
else // No probation
{
ACCEPTPACKETCODE
}
#else // No compiled-in probation support
ACCEPTPACKETCODE
#endif // RTP_SUPPORT_PROBATION
}
else // already got packets
{
uint16_t maxseq16;
uint32_t extseqnr;
// Adjust max extended sequence number and set extende seq nr of packet
*accept = true;
packetsreceived++;
numnewpackets++;
maxseq16 = (uint16_t)(exthighseqnr&0x0000FFFF);
if (pack->GetExtendedSequenceNumber() >= maxseq16)
{
extseqnr = numcycles+pack->GetExtendedSequenceNumber();
exthighseqnr = extseqnr;
}
else
{
uint16_t dif1,dif2;
dif1 = ((uint16_t)pack->GetExtendedSequenceNumber());
dif1 -= maxseq16;
dif2 = maxseq16;
dif2 -= ((uint16_t)pack->GetExtendedSequenceNumber());
if (dif1 < dif2)
{
numcycles += 0x00010000;
extseqnr = numcycles+pack->GetExtendedSequenceNumber();
exthighseqnr = extseqnr;
}
else
extseqnr = numcycles+pack->GetExtendedSequenceNumber();
}
pack->SetExtendedSequenceNumber(extseqnr);
// Calculate jitter
if (tsunit > 0)
{
#if 0
RTPTime curtime = receivetime;
double diffts1,diffts2,diff;
curtime -= prevpacktime;
diffts1 = curtime.GetDouble()/tsunit;
diffts2 = (double)pack->GetTimestamp() - (double)prevtimestamp;
diff = diffts1 - diffts2;
if (diff < 0)
diff = -diff;
diff -= djitter;
diff /= 16.0;
djitter += diff;
jitter = (uint32_t)djitter;
#else
RTPTime curtime = receivetime;
double diffts1,diffts2,diff;
uint32_t curts = pack->GetTimestamp();
curtime -= prevpacktime;
diffts1 = curtime.GetDouble()/tsunit;
if (curts > prevtimestamp)
{
uint32_t unsigneddiff = curts - prevtimestamp;
if (unsigneddiff < 0x10000000) // okay, curts realy is larger than prevtimestamp
diffts2 = (double)unsigneddiff;
else
{
// wraparound occurred and curts is actually smaller than prevtimestamp
unsigneddiff = -unsigneddiff; // to get the actual difference (in absolute value)
diffts2 = -((double)unsigneddiff);
}
}
else if (curts < prevtimestamp)
{
uint32_t unsigneddiff = prevtimestamp - curts;
if (unsigneddiff < 0x10000000) // okay, curts really is smaller than prevtimestamp
diffts2 = -((double)unsigneddiff); // negative since we actually need curts-prevtimestamp
else
{
// wraparound occurred and curts is actually larger than prevtimestamp
unsigneddiff = -unsigneddiff; // to get the actual difference (in absolute value)
diffts2 = (double)unsigneddiff;
}
}
else
diffts2 = 0;
diff = diffts1 - diffts2;
if (diff < 0)
diff = -diff;
diff -= djitter;
diff /= 16.0;
djitter += diff;
jitter = (uint32_t)djitter;
#endif
}
else
{
djitter = 0;
jitter = 0;
}
prevpacktime = receivetime;
prevtimestamp = pack->GetTimestamp();
lastmsgtime = prevpacktime;
if (!ownpacket) // for own packet, this value is set on an outgoing packet
lastrtptime = prevpacktime;
}
}
RTPSourceData::RTPSourceData(uint32_t s, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),SDESinf(mgr),byetime(0,0)
{
ssrc = s;
issender = false;
iscsrc = false;
timestampunit = -1;
receivedbye = false;
byereason = 0;
byereasonlen = 0;
rtpaddr = 0;
rtcpaddr = 0;
ownssrc = false;
validated = false;
processedinrtcp = false;
isrtpaddrset = false;
isrtcpaddrset = false;
}
RTPSourceData::~RTPSourceData()
{
FlushPackets();
if (byereason)
RTPDeleteByteArray(byereason,GetMemoryManager());
if (rtpaddr)
RTPDelete(rtpaddr,GetMemoryManager());
if (rtcpaddr)
RTPDelete(rtcpaddr,GetMemoryManager());
}
double RTPSourceData::INF_GetEstimatedTimestampUnit() const
{
if (!SRprevinf.HasInfo())
return -1.0;
RTPTime t1 = RTPTime(SRinf.GetNTPTimestamp());
RTPTime t2 = RTPTime(SRprevinf.GetNTPTimestamp());
if ((t1.GetSeconds() == 0 && t1.GetMicroSeconds() == 0) ||
(t2.GetSeconds() == 0 && t2.GetMicroSeconds() == 0)) // one of the times couldn't be calculated
return -1.0;
if (t1 <= t2)
return -1.0;
t1 -= t2; // get the time difference
uint32_t tsdiff = SRinf.GetRTPTimestamp()-SRprevinf.GetRTPTimestamp();
return (t1.GetDouble()/((double)tsdiff));
}
RTPTime RTPSourceData::INF_GetRoundtripTime() const
{
if (!RRinf.HasInfo())
return RTPTime(0,0);
if (RRinf.GetDelaySinceLastSR() == 0 && RRinf.GetLastSRTimestamp() == 0)
return RTPTime(0,0);
RTPNTPTime recvtime = RRinf.GetReceiveTime().GetNTPTime();
uint32_t rtt = ((recvtime.GetMSW()&0xFFFF)<<16)|((recvtime.GetLSW()>>16)&0xFFFF);
rtt -= RRinf.GetLastSRTimestamp();
rtt -= RRinf.GetDelaySinceLastSR();
double drtt = (((double)rtt)/65536.0);
return RTPTime(drtt);
}
#ifdef RTPDEBUG
void RTPSourceData::Dump()
{
std::cout << "Source data for SSRC: " << ssrc << std::endl;
std::cout << " Active: " << ((IsActive())?"Yes":"No") << std::endl;
std::cout << " Sender: " << ((issender)?"Yes":"No") << std::endl;
std::cout << " CSRC: " << ((iscsrc)?"Yes":"No") << std::endl;
std::cout << " Received bye: " << ((receivedbye)?"Yes":"No") << std::endl;
std::cout << " ProcessedInRTCP: " << ((processedinrtcp)?"Yes":"No") << std::endl;
std::cout << " Timestamp unit: " << timestampunit << std::endl;
std::cout << " RTP address: ";
if (!isrtpaddrset)
std::cout << "Not set" << std::endl;
else
{
if (rtpaddr == 0)
std::cout << "Own session" << std::endl;
else
std::cout << rtpaddr->GetAddressString() << std::endl;
}
std::cout << " RTCP address: ";
if (!isrtcpaddrset)
std::cout << "Not set" << std::endl;
else
{
if (rtcpaddr == 0)
std::cout << "Own session" << std::endl;
else
std::cout << rtcpaddr->GetAddressString() << std::endl;
}
if (SRinf.HasInfo())
{
if (!SRprevinf.HasInfo())
{
std::cout << " SR Info:" << std::endl;
std::cout << " NTP timestamp: " << SRinf.GetNTPTimestamp().GetMSW() << ":" << SRinf.GetNTPTimestamp().GetLSW() << std::endl;
std::cout << " RTP timestamp: " << SRinf.GetRTPTimestamp() << std::endl;
std::cout << " Packet count: " << SRinf.GetPacketCount() << std::endl;
std::cout << " Octet count: " << SRinf.GetByteCount() << std::endl;
std::cout << " Receive time: " << SRinf.GetReceiveTime().GetSeconds() << std::endl;
}
else
{
std::cout << " SR Info:" << std::endl;
std::cout << " NTP timestamp: " << SRinf.GetNTPTimestamp().GetMSW() << ":" << SRinf.GetNTPTimestamp().GetLSW()
<< " (" << SRprevinf.GetNTPTimestamp().GetMSW() << ":" << SRprevinf.GetNTPTimestamp().GetLSW() << ")" << std::endl;
std::cout << " RTP timestamp: " << SRinf.GetRTPTimestamp()
<< " (" << SRprevinf.GetRTPTimestamp() << ")" << std::endl;
std::cout << " Packet count: " << SRinf.GetPacketCount()
<< " (" << SRprevinf.GetPacketCount() << ")" << std::endl;
std::cout << " Octet count: " << SRinf.GetByteCount()
<< " (" << SRprevinf.GetByteCount() <<")" << std::endl;
std::cout << " Receive time: " << SRinf.GetReceiveTime().GetSeconds()
<< " (" << SRprevinf.GetReceiveTime().GetSeconds() << ")" << std::endl;
}
}
if (RRinf.HasInfo())
{
if (!RRprevinf.HasInfo())
{
std::cout << " RR Info:" << std::endl;
std::cout << " Fraction lost: " << RRinf.GetFractionLost() << std::endl;
std::cout << " Packets lost: " << RRinf.GetPacketsLost() << std::endl;
std::cout << " Ext.High.Seq: " << RRinf.GetExtendedHighestSequenceNumber() << std::endl;
std::cout << " Jitter: " << RRinf.GetJitter() << std::endl;
std::cout << " LSR: " << RRinf.GetLastSRTimestamp() << std::endl;
std::cout << " DLSR: " << RRinf.GetDelaySinceLastSR() << std::endl;
std::cout << " Receive time: " << RRinf.GetReceiveTime().GetSeconds() << std::endl;
}
else
{
std::cout << " RR Info:" << std::endl;
std::cout << " Fraction lost: " << RRinf.GetFractionLost()
<< " (" << RRprevinf.GetFractionLost() << ")" << std::endl;
std::cout << " Packets lost: " << RRinf.GetPacketsLost()
<< " (" << RRprevinf.GetPacketsLost() << ")" << std::endl;
std::cout << " Ext.High.Seq: " << RRinf.GetExtendedHighestSequenceNumber()
<< " (" << RRprevinf.GetExtendedHighestSequenceNumber() << ")" << std::endl;
std::cout << " Jitter: " << RRinf.GetJitter()
<< " (" << RRprevinf.GetJitter() << ")" << std::endl;
std::cout << " LSR: " << RRinf.GetLastSRTimestamp()
<< " (" << RRprevinf.GetLastSRTimestamp() << ")" << std::endl;
std::cout << " DLSR: " << RRinf.GetDelaySinceLastSR()
<< " (" << RRprevinf.GetDelaySinceLastSR() << ")" << std::endl;
std::cout << " Receive time: " << RRinf.GetReceiveTime().GetSeconds()
<< " (" << RRprevinf.GetReceiveTime().GetSeconds() <<")" << std::endl;
}
}
std::cout << " Stats:" << std::endl;
std::cout << " Sent data: " << ((stats.HasSentData())?"Yes":"No") << std::endl;
std::cout << " Packets received: " << stats.GetNumPacketsReceived() << std::endl;
std::cout << " Seq. base: " << stats.GetBaseSequenceNumber() << std::endl;
std::cout << " Ext.High.Seq: " << stats.GetExtendedHighestSequenceNumber() << std::endl;
std::cout << " Jitter: " << stats.GetJitter() << std::endl;
std::cout << " New packets: " << stats.GetNumPacketsReceivedInInterval() << std::endl;
std::cout << " Saved seq. nr.: " << stats.GetSavedExtendedSequenceNumber() << std::endl;
std::cout << " RTT: " << INF_GetRoundtripTime().GetDouble() << " seconds" << std::endl;
if (INF_GetEstimatedTimestampUnit() > 0)
std::cout << " Estimated: " << (1.0/INF_GetEstimatedTimestampUnit()) << " samples per second" << std::endl;
std::cout << " SDES Info:" << std::endl;
size_t len;
char str[1024];
uint8_t *val;
if ((val = SDESinf.GetCNAME(&len)) != 0)
{
memcpy(str,val,len);
str[len] = 0;
std::cout << " CNAME: " << std::string(str) << std::endl;
}
if ((val = SDESinf.GetName(&len)) != 0)
{
memcpy(str,val,len);
str[len] = 0;
std::cout << " Name: " << std::string(str) << std::endl;
}
if ((val = SDESinf.GetEMail(&len)) != 0)
{
memcpy(str,val,len);
str[len] = 0;
std::cout << " EMail: " << std::string(str) << std::endl;
}
if ((val = SDESinf.GetPhone(&len)) != 0)
{
memcpy(str,val,len);
str[len] = 0;
std::cout << " phone: " << std::string(str) << std::endl;
}
if ((val = SDESinf.GetLocation(&len)) != 0)
{
memcpy(str,val,len);
str[len] = 0;
std::cout << " Location: " << std::string(str) << std::endl;
}
if ((val = SDESinf.GetTool(&len)) != 0)
{
memcpy(str,val,len);
str[len] = 0;
std::cout << " Tool: " << std::string(str) << std::endl;
}
if ((val = SDESinf.GetNote(&len)) != 0)
{
memcpy(str,val,len);
str[len] = 0;
std::cout << " Note: " << std::string(str) << std::endl;
}
#ifdef RTP_SUPPORT_SDESPRIV
SDESinf.GotoFirstPrivateValue();
uint8_t *pref;
size_t preflen;
while (SDESinf.GetNextPrivateValue(&pref,&preflen,&val,&len))
{
char prefstr[1024];
memcpy(prefstr,pref,preflen);
memcpy(str,val,len);
prefstr[preflen] = 0;
str[len] = 0;
std::cout << " Private: " << std::string(prefstr) << ":" << std::string(str) << std::endl;
}
#endif // RTP_SUPPORT_SDESPRIV
if (byereason)
{
memcpy(str,byereason,byereasonlen);
str[byereasonlen] = 0;
std::cout << " BYE Reason: " << std::string(str) << std::endl;
}
}
#endif // RTPDEBUG
} // end namespace

View File

@@ -0,0 +1,480 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsourcedata.h
*/
#ifndef RTPSOURCEDATA_H
#define RTPSOURCEDATA_H
#include "rtpconfig.h"
#include "rtptimeutilities.h"
#include "rtppacket.h"
#include "rtcpsdesinfo.h"
#include "rtptypes.h"
#include "rtpsources.h"
#include "rtpmemoryobject.h"
#include <list>
namespace jrtplib
{
class RTPAddress;
class JRTPLIB_IMPORTEXPORT RTCPSenderReportInfo
{
public:
RTCPSenderReportInfo():ntptimestamp(0,0),receivetime(0,0) { hasinfo = false; rtptimestamp = 0; packetcount = 0; bytecount = 0; }
void Set(const RTPNTPTime &ntptime,uint32_t rtptime,uint32_t pcount,
uint32_t bcount,const RTPTime &rcvtime) { ntptimestamp = ntptime; rtptimestamp = rtptime; packetcount = pcount; bytecount = bcount; receivetime = rcvtime; hasinfo = true; }
bool HasInfo() const { return hasinfo; }
RTPNTPTime GetNTPTimestamp() const { return ntptimestamp; }
uint32_t GetRTPTimestamp() const { return rtptimestamp; }
uint32_t GetPacketCount() const { return packetcount; }
uint32_t GetByteCount() const { return bytecount; }
RTPTime GetReceiveTime() const { return receivetime; }
private:
bool hasinfo;
RTPNTPTime ntptimestamp;
uint32_t rtptimestamp;
uint32_t packetcount;
uint32_t bytecount;
RTPTime receivetime;
};
class JRTPLIB_IMPORTEXPORT RTCPReceiverReportInfo
{
public:
RTCPReceiverReportInfo():receivetime(0,0) { hasinfo = false; fractionlost = 0; packetslost = 0; exthighseqnr = 0; jitter = 0; lsr = 0; dlsr = 0; }
void Set(uint8_t fraclost,int32_t plost,uint32_t exthigh,
uint32_t jit,uint32_t l,uint32_t dl,const RTPTime &rcvtime) { fractionlost = ((double)fraclost)/256.0; packetslost = plost; exthighseqnr = exthigh; jitter = jit; lsr = l; dlsr = dl; receivetime = rcvtime; hasinfo = true; }
bool HasInfo() const { return hasinfo; }
double GetFractionLost() const { return fractionlost; }
int32_t GetPacketsLost() const { return packetslost; }
uint32_t GetExtendedHighestSequenceNumber() const { return exthighseqnr; }
uint32_t GetJitter() const { return jitter; }
uint32_t GetLastSRTimestamp() const { return lsr; }
uint32_t GetDelaySinceLastSR() const { return dlsr; }
RTPTime GetReceiveTime() const { return receivetime; }
private:
bool hasinfo;
double fractionlost;
int32_t packetslost;
uint32_t exthighseqnr;
uint32_t jitter;
uint32_t lsr;
uint32_t dlsr;
RTPTime receivetime;
};
class JRTPLIB_IMPORTEXPORT RTPSourceStats
{
public:
RTPSourceStats();
void ProcessPacket(RTPPacket *pack,const RTPTime &receivetime,double tsunit,bool ownpacket,bool *accept,bool applyprobation,bool *onprobation);
bool HasSentData() const { return sentdata; }
uint32_t GetNumPacketsReceived() const { return packetsreceived; }
uint32_t GetBaseSequenceNumber() const { return baseseqnr; }
uint32_t GetExtendedHighestSequenceNumber() const { return exthighseqnr; }
uint32_t GetJitter() const { return jitter; }
void ResetJitter() { jitter = 0; }
int32_t GetNumPacketsReceivedInInterval() const { return numnewpackets; }
uint32_t GetSavedExtendedSequenceNumber() const { return savedextseqnr; }
void StartNewInterval() { numnewpackets = 0; savedextseqnr = exthighseqnr; }
void SetLastMessageTime(const RTPTime &t) { lastmsgtime = t; }
RTPTime GetLastMessageTime() const { return lastmsgtime; }
void SetLastRTPPacketTime(const RTPTime &t) { lastrtptime = t; }
RTPTime GetLastRTPPacketTime() const { return lastrtptime; }
void SetLastNoteTime(const RTPTime &t) { lastnotetime = t; }
RTPTime GetLastNoteTime() const { return lastnotetime; }
private:
bool sentdata;
uint32_t packetsreceived;
uint32_t numcycles; // shifted left 16 bits
uint32_t baseseqnr;
uint32_t exthighseqnr,prevexthighseqnr;
uint32_t jitter,prevtimestamp;
double djitter;
RTPTime prevpacktime;
RTPTime lastmsgtime;
RTPTime lastrtptime;
RTPTime lastnotetime;
uint32_t numnewpackets;
uint32_t savedextseqnr;
#ifdef RTP_SUPPORT_PROBATION
uint16_t prevseqnr;
int probation;
RTPSources::ProbationType probationtype;
#endif // RTP_SUPPORT_PROBATION
};
inline RTPSourceStats::RTPSourceStats():prevpacktime(0,0),lastmsgtime(0,0),lastrtptime(0,0),lastnotetime(0,0)
{
sentdata = false;
packetsreceived = 0;
baseseqnr = 0;
exthighseqnr = 0;
prevexthighseqnr = 0;
jitter = 0;
numcycles = 0;
numnewpackets = 0;
prevtimestamp = 0;
djitter = 0;
savedextseqnr = 0;
#ifdef RTP_SUPPORT_PROBATION
probation = 0;
prevseqnr = 0;
#endif // RTP_SUPPORT_PROBATION
}
/** Describes an entry in the RTPSources source table. */
class JRTPLIB_IMPORTEXPORT RTPSourceData : public RTPMemoryObject
{
protected:
RTPSourceData(uint32_t ssrc, RTPMemoryManager *mgr = 0);
virtual ~RTPSourceData();
public:
/** Extracts the first packet of this participants RTP packet queue. */
RTPPacket *GetNextPacket();
/** Clears the participant's RTP packet list. */
void FlushPackets();
/** Returns \c true if there are RTP packets which can be extracted. */
bool HasData() const { if (!validated) return false; return packetlist.empty()?false:true; }
/** Returns the SSRC identifier for this member. */
uint32_t GetSSRC() const { return ssrc; }
/** Returns \c true if the participant was added using the RTPSources member function CreateOwnSSRC and
* returns \c false otherwise.
*/
bool IsOwnSSRC() const { return ownssrc; }
/** Returns \c true if the source identifier is actually a CSRC from an RTP packet. */
bool IsCSRC() const { return iscsrc; }
/** Returns \c true if this member is marked as a sender and \c false if not. */
bool IsSender() const { return issender; }
/** Returns \c true if the participant is validated, which is the case if a number of
* consecutive RTP packets have been received or if a CNAME item has been received for
* this participant.
*/
bool IsValidated() const { return validated; }
/** Returns \c true if the source was validated and had not yet sent a BYE packet. */
bool IsActive() const { if (!validated) return false; if (receivedbye) return false; return true; }
/** This function is used by the RTCPPacketBuilder class to mark whether this participant's
* information has been processed in a report block or not.
*/
void SetProcessedInRTCP(bool v) { processedinrtcp = v; }
/** This function is used by the RTCPPacketBuilder class and returns whether this participant
* has been processed in a report block or not.
*/
bool IsProcessedInRTCP() const { return processedinrtcp; }
/** Returns \c true if the address from which this participant's RTP packets originate has
* already been set.
*/
bool IsRTPAddressSet() const { return isrtpaddrset; }
/** Returns \c true if the address from which this participant's RTCP packets originate has
* already been set.
*/
bool IsRTCPAddressSet() const { return isrtcpaddrset; }
/** Returns the address from which this participant's RTP packets originate.
* Returns the address from which this participant's RTP packets originate. If the address has
* been set and the returned value is NULL, this indicates that it originated from the local
* participant.
*/
const RTPAddress *GetRTPDataAddress() const { return rtpaddr; }
/** Returns the address from which this participant's RTCP packets originate.
* Returns the address from which this participant's RTCP packets originate. If the address has
* been set and the returned value is NULL, this indicates that it originated from the local
* participant.
*/
const RTPAddress *GetRTCPDataAddress() const { return rtcpaddr; }
/** Returns \c true if we received a BYE message for this participant and \c false otherwise. */
bool ReceivedBYE() const { return receivedbye; }
/** Returns the reason for leaving contained in the BYE packet of this participant.
* Returns the reason for leaving contained in the BYE packet of this participant. The length of
* the reason is stored in \c len.
*/
uint8_t *GetBYEReason(size_t *len) const { *len = byereasonlen; return byereason; }
/** Returns the time at which the BYE packet was received. */
RTPTime GetBYETime() const { return byetime; }
/** Sets the value for the timestamp unit to be used in jitter calculations for data received from this participant.
* Sets the value for the timestamp unit to be used in jitter calculations for data received from this participant.
* If not set, the library uses an approximation for the timestamp unit which is calculated from two consecutive
* RTCP sender reports. The timestamp unit is defined as a time interval divided by the corresponding timestamp
* interval. For 8000 Hz audio this would be 1/8000. For video, often a timestamp unit of 1/90000 is used.
*/
void SetTimestampUnit(double tsu) { timestampunit = tsu; }
/** Returns the timestamp unit used for this participant. */
double GetTimestampUnit() const { return timestampunit; }
/** Returns \c true if an RTCP sender report has been received from this participant. */
bool SR_HasInfo() const { return SRinf.HasInfo(); }
/** Returns the NTP timestamp contained in the last sender report. */
RTPNTPTime SR_GetNTPTimestamp() const { return SRinf.GetNTPTimestamp(); }
/** Returns the RTP timestamp contained in the last sender report. */
uint32_t SR_GetRTPTimestamp() const { return SRinf.GetRTPTimestamp(); }
/** Returns the packet count contained in the last sender report. */
uint32_t SR_GetPacketCount() const { return SRinf.GetPacketCount(); }
/** Returns the octet count contained in the last sender report. */
uint32_t SR_GetByteCount() const { return SRinf.GetByteCount(); }
/** Returns the time at which the last sender report was received. */
RTPTime SR_GetReceiveTime() const { return SRinf.GetReceiveTime(); }
/** Returns \c true if more than one RTCP sender report has been received. */
bool SR_Prev_HasInfo() const { return SRprevinf.HasInfo(); }
/** Returns the NTP timestamp contained in the second to last sender report. */
RTPNTPTime SR_Prev_GetNTPTimestamp() const { return SRprevinf.GetNTPTimestamp(); }
/** Returns the RTP timestamp contained in the second to last sender report. */
uint32_t SR_Prev_GetRTPTimestamp() const { return SRprevinf.GetRTPTimestamp(); }
/** Returns the packet count contained in the second to last sender report. */
uint32_t SR_Prev_GetPacketCount() const { return SRprevinf.GetPacketCount(); }
/** Returns the octet count contained in the second to last sender report. */
uint32_t SR_Prev_GetByteCount() const { return SRprevinf.GetByteCount(); }
/** Returns the time at which the second to last sender report was received. */
RTPTime SR_Prev_GetReceiveTime() const { return SRprevinf.GetReceiveTime(); }
/** Returns \c true if this participant sent a receiver report with information about the reception of our data. */
bool RR_HasInfo() const { return RRinf.HasInfo(); }
/** Returns the fraction lost value from the last report. */
double RR_GetFractionLost() const { return RRinf.GetFractionLost(); }
/** Returns the number of lost packets contained in the last report. */
int32_t RR_GetPacketsLost() const { return RRinf.GetPacketsLost(); }
/** Returns the extended highest sequence number contained in the last report. */
uint32_t RR_GetExtendedHighestSequenceNumber() const { return RRinf.GetExtendedHighestSequenceNumber(); }
/** Returns the jitter value from the last report. */
uint32_t RR_GetJitter() const { return RRinf.GetJitter(); }
/** Returns the LSR value from the last report. */
uint32_t RR_GetLastSRTimestamp() const { return RRinf.GetLastSRTimestamp(); }
/** Returns the DLSR value from the last report. */
uint32_t RR_GetDelaySinceLastSR() const { return RRinf.GetDelaySinceLastSR(); }
/** Returns the time at which the last report was received. */
RTPTime RR_GetReceiveTime() const { return RRinf.GetReceiveTime(); }
/** Returns \c true if this participant sent more than one receiver report with information
* about the reception of our data.
*/
bool RR_Prev_HasInfo() const { return RRprevinf.HasInfo(); }
/** Returns the fraction lost value from the second to last report. */
double RR_Prev_GetFractionLost() const { return RRprevinf.GetFractionLost(); }
/** Returns the number of lost packets contained in the second to last report. */
int32_t RR_Prev_GetPacketsLost() const { return RRprevinf.GetPacketsLost(); }
/** Returns the extended highest sequence number contained in the second to last report. */
uint32_t RR_Prev_GetExtendedHighestSequenceNumber() const { return RRprevinf.GetExtendedHighestSequenceNumber(); }
/** Returns the jitter value from the second to last report. */
uint32_t RR_Prev_GetJitter() const { return RRprevinf.GetJitter(); }
/** Returns the LSR value from the second to last report. */
uint32_t RR_Prev_GetLastSRTimestamp() const { return RRprevinf.GetLastSRTimestamp(); }
/** Returns the DLSR value from the second to last report. */
uint32_t RR_Prev_GetDelaySinceLastSR() const { return RRprevinf.GetDelaySinceLastSR(); }
/** Returns the time at which the second to last report was received. */
RTPTime RR_Prev_GetReceiveTime() const { return RRprevinf.GetReceiveTime(); }
/** Returns \c true if validated RTP packets have been received from this participant. */
bool INF_HasSentData() const { return stats.HasSentData(); }
/** Returns the total number of received packets from this participant. */
int32_t INF_GetNumPacketsReceived() const { return stats.GetNumPacketsReceived(); }
/** Returns the base sequence number of this participant. */
uint32_t INF_GetBaseSequenceNumber() const { return stats.GetBaseSequenceNumber(); }
/** Returns the extended highest sequence number received from this participant. */
uint32_t INF_GetExtendedHighestSequenceNumber() const { return stats.GetExtendedHighestSequenceNumber(); }
/** Returns the current jitter value for this participant. */
uint32_t INF_GetJitter() const { return stats.GetJitter(); }
/** Returns the time at which something was last heard from this member. */
RTPTime INF_GetLastMessageTime() const { return stats.GetLastMessageTime(); }
/** Returns the time at which the last RTP packet was received. */
RTPTime INF_GetLastRTPPacketTime() const { return stats.GetLastRTPPacketTime(); }
/** Returns the estimated timestamp unit, calculated from two consecutive sender reports. */
double INF_GetEstimatedTimestampUnit() const;
/** Returns the number of packets received since a new interval was started with INF_StartNewInterval. */
uint32_t INF_GetNumPacketsReceivedInInterval() const { return stats.GetNumPacketsReceivedInInterval(); }
/** Returns the extended sequence number which was stored by the INF_StartNewInterval call. */
uint32_t INF_GetSavedExtendedSequenceNumber() const { return stats.GetSavedExtendedSequenceNumber(); }
/** Starts a new interval to count received packets in; this also stores the current extended highest sequence
* number to be able to calculate the packet loss during the interval.
*/
void INF_StartNewInterval() { stats.StartNewInterval(); }
/** Estimates the round trip time by using the LSR and DLSR info from the last receiver report. */
RTPTime INF_GetRoundtripTime() const;
/** Returns the time at which the last SDES NOTE item was received. */
RTPTime INF_GetLastSDESNoteTime() const { return stats.GetLastNoteTime(); }
/** Returns a pointer to the SDES CNAME item of this participant and stores its length in \c len. */
uint8_t *SDES_GetCNAME(size_t *len) const { return SDESinf.GetCNAME(len); }
/** Returns a pointer to the SDES name item of this participant and stores its length in \c len. */
uint8_t *SDES_GetName(size_t *len) const { return SDESinf.GetName(len); }
/** Returns a pointer to the SDES e-mail item of this participant and stores its length in \c len. */
uint8_t *SDES_GetEMail(size_t *len) const { return SDESinf.GetEMail(len); }
/** Returns a pointer to the SDES phone item of this participant and stores its length in \c len. */
uint8_t *SDES_GetPhone(size_t *len) const { return SDESinf.GetPhone(len); }
/** Returns a pointer to the SDES location item of this participant and stores its length in \c len. */
uint8_t *SDES_GetLocation(size_t *len) const { return SDESinf.GetLocation(len); }
/** Returns a pointer to the SDES tool item of this participant and stores its length in \c len. */
uint8_t *SDES_GetTool(size_t *len) const { return SDESinf.GetTool(len); }
/** Returns a pointer to the SDES note item of this participant and stores its length in \c len. */
uint8_t *SDES_GetNote(size_t *len) const { return SDESinf.GetNote(len); }
#ifdef RTP_SUPPORT_SDESPRIV
/** Starts the iteration over the stored SDES private item prefixes and their associated values. */
void SDES_GotoFirstPrivateValue() { SDESinf.GotoFirstPrivateValue(); }
/** If available, returns \c true and stores the next SDES private item prefix in \c prefix and its length in
* \c prefixlen; the associated value and its length are then stored in \c value and \c valuelen.
*/
bool SDES_GetNextPrivateValue(uint8_t **prefix,size_t *prefixlen,uint8_t **value,size_t *valuelen) { return SDESinf.GetNextPrivateValue(prefix,prefixlen,value,valuelen); }
/** Looks for the entry which corresponds to the SDES private item prefix \c prefix with length
* \c prefixlen; if found, the function returns \c true and stores the associated value and
* its length in \c value and \c valuelen respectively.
*/
bool SDES_GetPrivateValue(uint8_t *prefix,size_t prefixlen,uint8_t **value,size_t *valuelen) const { return SDESinf.GetPrivateValue(prefix,prefixlen,value,valuelen); }
#endif // RTP_SUPPORT_SDESPRIV
#ifdef RTPDEBUG
virtual void Dump();
#endif // RTPDEBUG
protected:
std::list<RTPPacket *> packetlist;
uint32_t ssrc;
bool ownssrc;
bool iscsrc;
double timestampunit;
bool receivedbye;
bool validated;
bool processedinrtcp;
bool issender;
RTCPSenderReportInfo SRinf,SRprevinf;
RTCPReceiverReportInfo RRinf,RRprevinf;
RTPSourceStats stats;
RTCPSDESInfo SDESinf;
bool isrtpaddrset,isrtcpaddrset;
RTPAddress *rtpaddr,*rtcpaddr;
RTPTime byetime;
uint8_t *byereason;
size_t byereasonlen;
};
inline RTPPacket *RTPSourceData::GetNextPacket()
{
if (!validated)
return 0;
RTPPacket *p;
if (packetlist.empty())
return 0;
p = *(packetlist.begin());
packetlist.pop_front();
return p;
}
inline void RTPSourceData::FlushPackets()
{
std::list<RTPPacket *>::const_iterator it;
for (it = packetlist.begin() ; it != packetlist.end() ; ++it)
RTPDelete(*it,GetMemoryManager());
packetlist.clear();
}
} // end namespace
#endif // RTPSOURCEDATA_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,365 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsources.h
*/
#ifndef RTPSOURCES_H
#define RTPSOURCES_H
#include "rtpconfig.h"
#include "rtpkeyhashtable.h"
#include "rtcpsdespacket.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
#define RTPSOURCES_HASHSIZE 8317
namespace jrtplib
{
class JRTPLIB_IMPORTEXPORT RTPSources_GetHashIndex
{
public:
static int GetIndex(const uint32_t &ssrc) { return ssrc%RTPSOURCES_HASHSIZE; }
};
class RTPNTPTime;
class RTPTransmitter;
class RTCPAPPPacket;
class RTPInternalSourceData;
class RTPRawPacket;
class RTPPacket;
class RTPTime;
class RTPAddress;
class RTPSourceData;
/** Represents a table in which information about the participating sources is kept.
* Represents a table in which information about the participating sources is kept. The class has member
* functions to process RTP and RTCP data and to iterate over the participants. Note that a NULL address
* is used to identify packets from our own session. The class also provides some overridable functions
* which can be used to catch certain events (new SSRC, SSRC collision, ...).
*/
class JRTPLIB_IMPORTEXPORT RTPSources : public RTPMemoryObject
{
public:
/** Type of probation to use for new sources. */
enum ProbationType
{
NoProbation, /**< Don't use the probation algorithm; accept RTP packets immediately. */
ProbationDiscard, /**< Discard incoming RTP packets originating from a source that's on probation. */
ProbationStore /**< Store incoming RTP packet from a source that's on probation for later retrieval. */
};
/** In the constructor you can select the probation type you'd like to use and also a memory manager. */
RTPSources(ProbationType = ProbationStore,RTPMemoryManager *mgr = 0);
virtual ~RTPSources();
/** Clears the source table. */
void Clear();
#ifdef RTP_SUPPORT_PROBATION
/** Changes the current probation type. */
void SetProbationType(ProbationType probtype) { probationtype = probtype; }
#endif // RTP_SUPPORT_PROBATION
/** Creates an entry for our own SSRC identifier. */
int CreateOwnSSRC(uint32_t ssrc);
/** Deletes the entry for our own SSRC identifier. */
int DeleteOwnSSRC();
/** This function should be called if our own session has sent an RTP packet.
* This function should be called if our own session has sent an RTP packet.
* For our own SSRC entry, the sender flag is updated based upon outgoing packets instead of incoming packets.
*/
void SentRTPPacket();
/** Processes a raw packet \c rawpack.
* Processes a raw packet \c rawpack. The instance \c trans will be used to check if this
* packet is one of our own packets. The flag \c acceptownpackets indicates whether own packets should be
* accepted or ignored.
*/
int ProcessRawPacket(RTPRawPacket *rawpack,RTPTransmitter *trans,bool acceptownpackets);
/** Processes a raw packet \c rawpack.
* Processes a raw packet \c rawpack. Every transmitter in the array \c trans of length \c numtrans
* is used to check if the packet is from our own session. The flag \c acceptownpackets indicates
* whether own packets should be accepted or ignored.
*/
int ProcessRawPacket(RTPRawPacket *rawpack,RTPTransmitter *trans[],int numtrans,bool acceptownpackets);
/** Processes an RTPPacket instance \c rtppack which was received at time \c receivetime and
* which originated from \c senderaddres.
* Processes an RTPPacket instance \c rtppack which was received at time \c receivetime and
* which originated from \c senderaddres. The \c senderaddress parameter must be NULL if
* the packet was sent by the local participant. The flag \c stored indicates whether the packet
* was stored in the table or not. If so, the \c rtppack instance may not be deleted.
*/
int ProcessRTPPacket(RTPPacket *rtppack,const RTPTime &receivetime,const RTPAddress *senderaddress,bool *stored);
/** Processes the RTCP compound packet \c rtcpcomppack which was received at time \c receivetime from \c senderaddress.
* Processes the RTCP compound packet \c rtcpcomppack which was received at time \c receivetime from \c senderaddress.
* The \c senderaddress parameter must be NULL if the packet was sent by the local participant.
*/
int ProcessRTCPCompoundPacket(RTCPCompoundPacket *rtcpcomppack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Process the sender information of SSRC \c ssrc into the source table.
* Process the sender information of SSRC \c ssrc into the source table. The information was received
* at time \c receivetime from address \c senderaddress. The \c senderaddress} parameter must be NULL
* if the packet was sent by the local participant.
*/
int ProcessRTCPSenderInfo(uint32_t ssrc,const RTPNTPTime &ntptime,uint32_t rtptime,
uint32_t packetcount,uint32_t octetcount,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Processes the report block information which was sent by participant \c ssrc into the source table.
* Processes the report block information which was sent by participant \c ssrc into the source table.
* The information was received at time \c receivetime from address \c senderaddress The \c senderaddress
* parameter must be NULL if the packet was sent by the local participant.
*/
int ProcessRTCPReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t lostpackets,
uint32_t exthighseqnr,uint32_t jitter,uint32_t lsr,
uint32_t dlsr,const RTPTime &receivetime,const RTPAddress *senderaddress);
/** Processes the non-private SDES item from source \c ssrc into the source table.
* Processes the non-private SDES item from source \c ssrc into the source table. The information was
* received at time \c receivetime from address \c senderaddress. The \c senderaddress parameter must
* be NULL if the packet was sent by the local participant.
*/
int ProcessSDESNormalItem(uint32_t ssrc,RTCPSDESPacket::ItemType t,size_t itemlength,
const void *itemdata,const RTPTime &receivetime,const RTPAddress *senderaddress);
#ifdef RTP_SUPPORT_SDESPRIV
/** Processes the SDES private item from source \c ssrc into the source table.
* Processes the SDES private item from source \c ssrc into the source table. The information was
* received at time \c receivetime from address \c senderaddress. The \c senderaddress
* parameter must be NULL if the packet was sent by the local participant.
*/
int ProcessSDESPrivateItem(uint32_t ssrc,size_t prefixlen,const void *prefixdata,
size_t valuelen,const void *valuedata,const RTPTime &receivetime,
const RTPAddress *senderaddress);
#endif //RTP_SUPPORT_SDESPRIV
/** Processes the BYE message for SSRC \c ssrc.
* Processes the BYE message for SSRC \c ssrc. The information was received at time \c receivetime from
* address \c senderaddress. The \c senderaddress parameter must be NULL if the packet was sent by the
* local participant.
*/
int ProcessBYE(uint32_t ssrc,size_t reasonlength,const void *reasondata,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** If we heard from source \c ssrc, but no actual data was added to the source table (for example, if
* no report block was meant for us), this function can e used to indicate that something was received from
* this source.
* If we heard from source \c ssrc, but no actual data was added to the source table (for example, if
* no report block was meant for us), this function can e used to indicate that something was received from
* this source. This will prevent a premature timeout for this participant. The message was received at time
* \c receivetime from address \c senderaddress. The \c senderaddress parameter must be NULL if the
* packet was sent by the local participant.
*/
int UpdateReceiveTime(uint32_t ssrc,const RTPTime &receivetime,const RTPAddress *senderaddress);
/** Starts the iteration over the participants by going to the first member in the table.
* Starts the iteration over the participants by going to the first member in the table.
* If a member was found, the function returns \c true, otherwise it returns \c false.
*/
bool GotoFirstSource();
/** Sets the current source to be the next source in the table.
* Sets the current source to be the next source in the table. If we're already at the last source,
* the function returns \c false, otherwise it returns \c true.
*/
bool GotoNextSource();
/** Sets the current source to be the previous source in the table.
* Sets the current source to be the previous source in the table. If we're at the first source,
* the function returns \c false, otherwise it returns \c true.
*/
bool GotoPreviousSource();
/** Sets the current source to be the first source in the table which has RTPPacket instances
* that we haven't extracted yet.
* Sets the current source to be the first source in the table which has RTPPacket instances
* that we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoFirstSourceWithData();
/** Sets the current source to be the next source in the table which has RTPPacket instances that
* we haven't extracted yet.
* Sets the current source to be the next source in the table which has RTPPacket instances that
* we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoNextSourceWithData();
/** Sets the current source to be the previous source in the table which has RTPPacket instances
* that we haven't extracted yet.
* Sets the current source to be the previous source in the table which has RTPPacket instances
* that we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoPreviousSourceWithData();
/** Returns the RTPSourceData instance for the currently selected participant. */
RTPSourceData *GetCurrentSourceInfo();
/** Returns the RTPSourceData instance for the participant identified by \c ssrc, or
* NULL if no such entry exists.
*/
RTPSourceData *GetSourceInfo(uint32_t ssrc);
/** Extracts the next packet from the received packets queue of the current participant. */
RTPPacket *GetNextPacket();
/** Returns \c true if an entry for participant \c ssrc exists and \c false otherwise. */
bool GotEntry(uint32_t ssrc);
/** If present, it returns the RTPSourceData instance of the entry which was created by CreateOwnSSRC. */
RTPSourceData *GetOwnSourceInfo() { return (RTPSourceData *)owndata; }
/** Assuming that the current time is \c curtime, time out the members from whom we haven't heard
* during the previous time interval \c timeoutdelay.
*/
void Timeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
/** Assuming that the current time is \c curtime, remove the sender flag for senders from whom we haven't
* received any RTP packets during the previous time interval \c timeoutdelay.
*/
void SenderTimeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
/** Assuming that the current time is \c curtime, remove the members who sent a BYE packet more than
* the time interval \c timeoutdelay ago.
*/
void BYETimeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
/** Assuming that the current time is \c curtime, clear the SDES NOTE items which haven't been updated
* during the previous time interval \c timeoutdelay.
*/
void NoteTimeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
/** Combines the functions SenderTimeout, BYETimeout, Timeout and NoteTimeout.
* Combines the functions SenderTimeout, BYETimeout, Timeout and NoteTimeout. This is more efficient
* than calling all four functions since only one iteration is needed in this function.
*/
void MultipleTimeouts(const RTPTime &curtime,const RTPTime &sendertimeout,
const RTPTime &byetimeout,const RTPTime &generaltimeout,
const RTPTime &notetimeout);
/** Returns the number of participants which are marked as a sender. */
int GetSenderCount() const { return sendercount; }
/** Returns the total number of entries in the source table. */
int GetTotalCount() const { return totalcount; }
/** Returns the number of members which have been validated and which haven't sent a BYE packet yet. */
int GetActiveMemberCount() const { return activecount; }
#ifdef RTPDEBUG
void Dump();
void SafeCountTotal();
void SafeCountSenders();
void SafeCountActive();
#endif // RTPDEBUG
protected:
/** Is called when an RTP packet is about to be processed. */
virtual void OnRTPPacket(RTPPacket * /*pack*/,const RTPTime &/*receivetime*/, const RTPAddress * /*senderaddress*/) { }
/** Is called when an RTCP compound packet is about to be processed. */
virtual void OnRTCPCompoundPacket(RTCPCompoundPacket * /*pack*/,const RTPTime & /*receivetime*/,
const RTPAddress * /*senderaddress*/) { }
/** Is called when an SSRC collision was detected.
* Is called when an SSRC collision was detected. The instance \c srcdat is the one present in
* the table, the address \c senderaddress is the one that collided with one of the addresses
* and \c isrtp indicates against which address of \c srcdat the check failed.
*/
virtual void OnSSRCCollision(RTPSourceData * /*srcdat*/,const RTPAddress * /*senderaddress*/,bool /*isrtp*/) { }
/** Is called when another CNAME was received than the one already present for source \c srcdat. */
virtual void OnCNAMECollision(RTPSourceData * /*srcdat*/,const RTPAddress * /*senderaddress*/,
const uint8_t * /*cname*/,size_t /*cnamelength*/) { }
/** Is called when a new entry \c srcdat is added to the source table. */
virtual void OnNewSource(RTPSourceData * /*srcdat*/) { }
/** Is called when the entry \c srcdat is about to be deleted from the source table. */
virtual void OnRemoveSource(RTPSourceData * /*srcdat*/) { }
/** Is called when participant \c srcdat is timed out. */
virtual void OnTimeout(RTPSourceData * /*srcdat*/) { }
/** Is called when participant \c srcdat is timed after having sent a BYE packet. */
virtual void OnBYETimeout(RTPSourceData * /*srcdat*/) { }
/** Is called when a BYE packet has been processed for source \c srcdat. */
virtual void OnBYEPacket(RTPSourceData * /*srcdat*/) { }
/** Is called when an RTCP APP packet \c apppacket has been received at time \c receivetime
* from address \c senderaddress.
*/
virtual void OnAPPPacket(RTCPAPPPacket * /*apppacket*/,const RTPTime &/*receivetime*/,
const RTPAddress * /*senderaddress*/) { }
/** Is called when an unknown RTCP packet type was detected. */
virtual void OnUnknownPacketType(RTCPPacket * /*rtcppack*/,const RTPTime &/*receivetime*/,
const RTPAddress * /*senderaddress*/) { }
/** Is called when an unknown packet format for a known packet type was detected. */
virtual void OnUnknownPacketFormat(RTCPPacket * /*rtcppack*/,const RTPTime &/*receivetime*/,
const RTPAddress * /*senderaddress*/) { }
/** Is called when the SDES NOTE item for source \c srcdat has been timed out. */
virtual void OnNoteTimeout(RTPSourceData * /*srcdat*/) { }
private:
void ClearSourceList();
int ObtainSourceDataInstance(uint32_t ssrc,RTPInternalSourceData **srcdat,bool *created);
int GetRTCPSourceData(uint32_t ssrc,const RTPAddress *senderaddress,RTPInternalSourceData **srcdat,bool *newsource);
bool CheckCollision(RTPInternalSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp);
RTPKeyHashTable<const uint32_t,RTPInternalSourceData*,RTPSources_GetHashIndex,RTPSOURCES_HASHSIZE> sourcelist;
int sendercount;
int totalcount;
int activecount;
#ifdef RTP_SUPPORT_PROBATION
ProbationType probationtype;
#endif // RTP_SUPPORT_PROBATION
RTPInternalSourceData *owndata;
};
} // end namespace
#endif // RTPSOURCES_H

Some files were not shown because too many files have changed in this diff Show More