Explorar el Código

V1.1.0 加入jrtplib

huihui hace 5 años
padre
commit
8b06a44278
Se han modificado 100 ficheros con 19252 adiciones y 8 borrados
  1. 4 0
      .gitignore
  2. 27 8
      ScreenSender.pro
  3. BIN
      bin32/ScreenSender.exe
  4. BIN
      bin32/ScreenSender.ilk
  5. BIN
      bin32/ScreenSender.pdb
  6. BIN
      bin32/VideoEncode.exe
  7. BIN
      bin32/VideoEncode.ilk
  8. BIN
      bin32/VideoEncode.pdb
  9. 3 0
      bin32/audio.sdp
  10. 0 0
      bin32/out.h264
  11. 9 0
      bin32/w.sdp
  12. BIN
      bin64/ScreenSender
  13. BIN
      bin64/ScreenSender.exe
  14. 0 0
      bin64/out.h264
  15. 108 0
      lib/common/jrtplib/jrtplib.pri
  16. 129 0
      lib/common/jrtplib/src/CMakeLists.txt
  17. 2 0
      lib/common/jrtplib/src/errcodecommand
  18. 1726 0
      lib/common/jrtplib/src/extratransmitters/rtpfaketransmitter.cpp
  19. 247 0
      lib/common/jrtplib/src/extratransmitters/rtpfaketransmitter.h
  20. 87 0
      lib/common/jrtplib/src/jmutex.cpp
  21. 75 0
      lib/common/jrtplib/src/jmutex.h
  22. 50 0
      lib/common/jrtplib/src/jmutexautolock.h
  23. 182 0
      lib/common/jrtplib/src/jthread.cpp
  24. 83 0
      lib/common/jrtplib/src/jthread.h
  25. 45 0
      lib/common/jrtplib/src/jthreadconfig.h
  26. 45 0
      lib/common/jrtplib/src/jthreadconfig.h.in
  27. 93 0
      lib/common/jrtplib/src/rtcpapppacket.cpp
  28. 132 0
      lib/common/jrtplib/src/rtcpapppacket.h
  29. 104 0
      lib/common/jrtplib/src/rtcpbyepacket.cpp
  30. 140 0
      lib/common/jrtplib/src/rtcpbyepacket.h
  31. 232 0
      lib/common/jrtplib/src/rtcpcompoundpacket.cpp
  32. 111 0
      lib/common/jrtplib/src/rtcpcompoundpacket.h
  33. 815 0
      lib/common/jrtplib/src/rtcpcompoundpacketbuilder.cpp
  34. 400 0
      lib/common/jrtplib/src/rtcpcompoundpacketbuilder.h
  35. 76 0
      lib/common/jrtplib/src/rtcppacket.cpp
  36. 94 0
      lib/common/jrtplib/src/rtcppacket.h
  37. 741 0
      lib/common/jrtplib/src/rtcppacketbuilder.cpp
  38. 229 0
      lib/common/jrtplib/src/rtcppacketbuilder.h
  39. 100 0
      lib/common/jrtplib/src/rtcprrpacket.cpp
  40. 206 0
      lib/common/jrtplib/src/rtcprrpacket.h
  41. 423 0
      lib/common/jrtplib/src/rtcpscheduler.cpp
  42. 189 0
      lib/common/jrtplib/src/rtcpscheduler.h
  43. 182 0
      lib/common/jrtplib/src/rtcpsdesinfo.cpp
  44. 220 0
      lib/common/jrtplib/src/rtcpsdesinfo.h
  45. 236 0
      lib/common/jrtplib/src/rtcpsdespacket.cpp
  46. 386 0
      lib/common/jrtplib/src/rtcpsdespacket.h
  47. 106 0
      lib/common/jrtplib/src/rtcpsrpacket.cpp
  48. 252 0
      lib/common/jrtplib/src/rtcpsrpacket.h
  49. 73 0
      lib/common/jrtplib/src/rtcpunknownpacket.h
  50. 99 0
      lib/common/jrtplib/src/rtpaddress.h
  51. 105 0
      lib/common/jrtplib/src/rtpbyteaddress.cpp
  52. 93 0
      lib/common/jrtplib/src/rtpbyteaddress.h
  53. 130 0
      lib/common/jrtplib/src/rtpcollisionlist.cpp
  54. 95 0
      lib/common/jrtplib/src/rtpcollisionlist.h
  55. 78 0
      lib/common/jrtplib/src/rtpconfig.h
  56. 78 0
      lib/common/jrtplib/src/rtpconfig.h.in
  57. 178 0
      lib/common/jrtplib/src/rtpdebug.cpp
  58. 52 0
      lib/common/jrtplib/src/rtpdebug.h
  59. 86 0
      lib/common/jrtplib/src/rtpdefines.h
  60. 257 0
      lib/common/jrtplib/src/rtperrors.cpp
  61. 236 0
      lib/common/jrtplib/src/rtperrors.h
  62. 925 0
      lib/common/jrtplib/src/rtpexternaltransmitter.cpp
  63. 241 0
      lib/common/jrtplib/src/rtpexternaltransmitter.h
  64. 342 0
      lib/common/jrtplib/src/rtphashtable.h
  65. 287 0
      lib/common/jrtplib/src/rtpinternalsourcedata.cpp
  66. 135 0
      lib/common/jrtplib/src/rtpinternalsourcedata.h
  67. 89 0
      lib/common/jrtplib/src/rtpipv4address.cpp
  68. 95 0
      lib/common/jrtplib/src/rtpipv4address.h
  69. 113 0
      lib/common/jrtplib/src/rtpipv4destination.h
  70. 113 0
      lib/common/jrtplib/src/rtpipv6address.cpp
  71. 110 0
      lib/common/jrtplib/src/rtpipv6address.h
  72. 114 0
      lib/common/jrtplib/src/rtpipv6destination.h
  73. 344 0
      lib/common/jrtplib/src/rtpkeyhashtable.h
  74. 55 0
      lib/common/jrtplib/src/rtplibraryversion.cpp
  75. 77 0
      lib/common/jrtplib/src/rtplibraryversion.h
  76. 257 0
      lib/common/jrtplib/src/rtpmemorymanager.h
  77. 74 0
      lib/common/jrtplib/src/rtpmemoryobject.h
  78. 350 0
      lib/common/jrtplib/src/rtppacket.cpp
  79. 183 0
      lib/common/jrtplib/src/rtppacket.h
  80. 274 0
      lib/common/jrtplib/src/rtppacketbuilder.cpp
  81. 274 0
      lib/common/jrtplib/src/rtppacketbuilder.h
  82. 180 0
      lib/common/jrtplib/src/rtppollthread.cpp
  83. 79 0
      lib/common/jrtplib/src/rtppollthread.h
  84. 86 0
      lib/common/jrtplib/src/rtprandom.cpp
  85. 76 0
      lib/common/jrtplib/src/rtprandom.h
  86. 125 0
      lib/common/jrtplib/src/rtprandomrand48.cpp
  87. 76 0
      lib/common/jrtplib/src/rtprandomrand48.h
  88. 200 0
      lib/common/jrtplib/src/rtprandomrands.cpp
  89. 70 0
      lib/common/jrtplib/src/rtprandomrands.h
  90. 123 0
      lib/common/jrtplib/src/rtprandomurandom.cpp
  91. 68 0
      lib/common/jrtplib/src/rtprandomurandom.h
  92. 114 0
      lib/common/jrtplib/src/rtprawpacket.h
  93. 1659 0
      lib/common/jrtplib/src/rtpsession.cpp
  94. 581 0
      lib/common/jrtplib/src/rtpsession.h
  95. 88 0
      lib/common/jrtplib/src/rtpsessionparams.cpp
  96. 248 0
      lib/common/jrtplib/src/rtpsessionparams.h
  97. 114 0
      lib/common/jrtplib/src/rtpsessionsources.cpp
  98. 84 0
      lib/common/jrtplib/src/rtpsessionsources.h
  99. 500 0
      lib/common/jrtplib/src/rtpsourcedata.cpp
  100. 480 0
      lib/common/jrtplib/src/rtpsourcedata.h

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+/bin32/out-L.pcm
+/bin32/out-R.pcm
+/bin32/ScreenSender.pdb
+bin32/out.h264

+ 27 - 8
ScreenSender.pro

@@ -28,18 +28,29 @@ contains(QT_ARCH, i386) {
 
 SOURCES += \
         src/AppConfig.cpp \
+        src/Media/Audio/AudioEncoder.cpp \
+        src/Media/Audio/AudioFrame/AACFrame.cpp \
+        src/Media/Audio/AudioFrame/PCMFrame.cpp \
+        src/Media/Audio/GetAudioThread.cpp \
+        src/Media/MediaReader.cpp \
         src/Mutex/Cond.cpp \
         src/Mutex/Mutex.cpp \
         src/NALU/nalu.cpp \
         src/RtpSender/RtpSender.cpp \
         src/RtpSender/RtpSenderManager.cpp \
-        src/Video/GetVideoThread.cpp \
-        src/Video/VideoEncoder.cpp \
+        src/Media/Video/GetVideoThread.cpp \
+        src/Media/Video/VideoEncoder.cpp \
         src/main.cpp \
-        src/mainwindow.cpp
+        src/mainwindow.cpp \
+    src/Media/Video/VideoFrame/VideoFrame.cpp
 
 HEADERS += \
     src/AppConfig.h \
+    src/Media/Audio/AudioEncoder.h \
+    src/Media/Audio/AudioFrame/AACFrame.h \
+    src/Media/Audio/AudioFrame/PCMFrame.h \
+    src/Media/Audio/GetAudioThread.h \
+    src/Media/MediaReader.h \
     src/Mutex/Cond.h \
     src/Mutex/Mutex.h \
     src/NALU/h264.h \
@@ -48,12 +59,15 @@ HEADERS += \
     src/RtpSender/RtpSender.h \
     src/RtpSender/RtpSenderManager.h \
     src/RtpSender/rtp.h \
-    src/Video/GetVideoThread.h \
-    src/Video/VideoEncoder.h \
-    src/mainwindow.h
+    src/Media/Video/GetVideoThread.h \
+    src/Media/Video/VideoEncoder.h \
+    src/mainwindow.h \
+    src/Media/Video/VideoFrame/VideoFrame.h
 
 win32{
 
+    include($$PWD/lib/common/jrtplib/jrtplib.pri)
+
     contains(QT_ARCH, i386) {
         message("32-bit")
         INCLUDEPATH += $$PWD/lib/win32/ffmpeg/include \
@@ -79,11 +93,15 @@ unix{
         message("32-bit, 请自行编译32位库!")
     } else {
         message("64-bit")
-        INCLUDEPATH += $$PWD/lib/linux/ffmpeg/include \
-                       $$PWD/src
+        INCLUDEPATH += $$PWD/src \
+                       $$PWD/lib/linux/ffmpeg/include \
+                       $$PWD/lib/linux/jrtplib/include/jrtplib3
+
 
         LIBS += -L$$PWD/lib/linux/ffmpeg/lib  -lavformat  -lavcodec -lavdevice -lavfilter -lavutil -lswresample -lswscale -lpostproc
 
+        LIBS += -L$$PWD/lib/linux/jrtplib/lib -ljrtp
+
         LIBS += -lpthread -ldl -lxcb
     }
 
@@ -93,6 +111,7 @@ unix{
 #解压库文件
 #QMAKE_PRE_LINK += "cd $$PWD/lib/linux && tar xvzf ffmpeg.tar.gz "
 system("cd $$PWD/lib/linux && tar xvzf ffmpeg.tar.gz")
+system("cd $$PWD/lib/linux && tar xvzf jrtplib.tar.gz")
 
 }
 

BIN
bin32/ScreenSender.exe


BIN
bin32/ScreenSender.ilk


BIN
bin32/ScreenSender.pdb


BIN
bin32/VideoEncode.exe


BIN
bin32/VideoEncode.ilk


BIN
bin32/VideoEncode.pdb


+ 3 - 0
bin32/audio.sdp

@@ -0,0 +1,3 @@
+m=audio 6000 RTP/AVP 97
+c=IN IP4 127.0.0.1
+a=rtpmap:97 mpeg4-generic/44100/2

+ 0 - 0
bin32/out.h264


+ 9 - 0
bin32/w.sdp

@@ -0,0 +1,9 @@
+m=video 8000 RTP/AVP 96
+a=rtpmap:96 H264
+a=framerate:15
+a=control:track1
+c=IN IP4 127.0.0.1
+m=audio 6000 RTP/AVP 97
+c=IN IP4 127.0.0.1
+a=rtpmap:97 mpeg4-generic/44100/2
+a=control:track2

BIN
bin64/ScreenSender


BIN
bin64/ScreenSender.exe


+ 0 - 0
bin64/out.h264


+ 108 - 0
lib/common/jrtplib/jrtplib.pri

@@ -0,0 +1,108 @@
+
+INCLUDEPATH += $$PWD/src
+
+OTHER_FILES += \
+    $$PWD/src/rtptypes.h.in \
+    $$PWD/src/errcodecommand \
+    $$PWD/src/CMakeLists.txt
+
+SOURCES += \
+    $$PWD/src/rtpudpv6transmitter.cpp \
+    $$PWD/src/rtpudpv4transmitter.cpp \
+    $$PWD/src/rtptimeutilities.cpp \
+    $$PWD/src/rtpsources.cpp \
+    $$PWD/src/rtpsourcedata.cpp \
+    $$PWD/src/rtpsessionsources.cpp \
+    $$PWD/src/rtpsessionparams.cpp \
+    $$PWD/src/rtpsession.cpp \
+    $$PWD/src/rtprandomurandom.cpp \
+    $$PWD/src/rtprandomrands.cpp \
+    $$PWD/src/rtprandomrand48.cpp \
+    $$PWD/src/rtprandom.cpp \
+    $$PWD/src/rtppollthread.cpp \
+    $$PWD/src/rtppacketbuilder.cpp \
+    $$PWD/src/rtppacket.cpp \
+    $$PWD/src/rtplibraryversion.cpp \
+    $$PWD/src/rtpipv6address.cpp \
+    $$PWD/src/rtpipv4address.cpp \
+    $$PWD/src/rtpinternalsourcedata.cpp \
+    $$PWD/src/rtpexternaltransmitter.cpp \
+    $$PWD/src/rtperrors.cpp \
+    $$PWD/src/rtpdebug.cpp \
+    $$PWD/src/rtpcollisionlist.cpp \
+    $$PWD/src/rtpbyteaddress.cpp \
+    $$PWD/src/rtcpsrpacket.cpp \
+    $$PWD/src/rtcpsdespacket.cpp \
+    $$PWD/src/rtcpsdesinfo.cpp \
+    $$PWD/src/rtcpscheduler.cpp \
+    $$PWD/src/rtcprrpacket.cpp \
+    $$PWD/src/rtcppacketbuilder.cpp \
+    $$PWD/src/rtcppacket.cpp \
+    $$PWD/src/rtcpcompoundpacketbuilder.cpp \
+    $$PWD/src/rtcpcompoundpacket.cpp \
+    $$PWD/src/rtcpbyepacket.cpp \
+    $$PWD/src/rtcpapppacket.cpp \
+    $$PWD/src/jthread.cpp \
+    $$PWD/src/jmutex.cpp
+
+HEADERS  += \
+    $$PWD/src/rtpudpv6transmitter.h \
+    $$PWD/src/rtpudpv4transmitter.h \
+    $$PWD/src/rtptypes_win.h \
+    $$PWD/src/rtptypes.h \
+    $$PWD/src/rtptransmitter.h \
+    $$PWD/src/rtptimeutilities.h \
+    $$PWD/src/rtpstructs.h \
+    $$PWD/src/rtpsources.h \
+    $$PWD/src/rtpsourcedata.h \
+    $$PWD/src/rtpsessionsources.h \
+    $$PWD/src/rtpsessionparams.h \
+    $$PWD/src/rtpsession.h \
+    $$PWD/src/rtprawpacket.h \
+    $$PWD/src/rtprandomurandom.h \
+    $$PWD/src/rtprandomrands.h \
+    $$PWD/src/rtprandomrand48.h \
+    $$PWD/src/rtprandom.h \
+    $$PWD/src/rtppollthread.h \
+    $$PWD/src/rtppacketbuilder.h \
+    $$PWD/src/rtppacket.h \
+    $$PWD/src/rtpmemoryobject.h \
+    $$PWD/src/rtpmemorymanager.h \
+    $$PWD/src/rtplibraryversion.h \
+    $$PWD/src/rtpkeyhashtable.h \
+    $$PWD/src/rtpipv6destination.h \
+    $$PWD/src/rtpipv6address.h \
+    $$PWD/src/rtpipv4destination.h \
+    $$PWD/src/rtpipv4address.h \
+    $$PWD/src/rtpinternalsourcedata.h \
+    $$PWD/src/rtphashtable.h \
+    $$PWD/src/rtpexternaltransmitter.h \
+    $$PWD/src/rtperrors.h \
+    $$PWD/src/rtpdefines.h \
+    $$PWD/src/rtpdebug.h \
+    $$PWD/src/rtpconfig.h.in \
+    $$PWD/src/rtpconfig.h \
+    $$PWD/src/rtpcollisionlist.h \
+    $$PWD/src/rtpbyteaddress.h \
+    $$PWD/src/rtpaddress.h \
+    $$PWD/src/rtcpunknownpacket.h \
+    $$PWD/src/rtcpsrpacket.h \
+    $$PWD/src/rtcpsdespacket.h \
+    $$PWD/src/rtcpsdesinfo.h \
+    $$PWD/src/rtcpscheduler.h \
+    $$PWD/src/rtcprrpacket.h \
+    $$PWD/src/rtcppacketbuilder.h \
+    $$PWD/src/rtcppacket.h \
+    $$PWD/src/rtcpcompoundpacketbuilder.h \
+    $$PWD/src/rtcpcompoundpacket.h \
+    $$PWD/src/rtcpbyepacket.h \
+    $$PWD/src/rtcpapppacket.h \
+    $$PWD/src/jthreadconfig.h.in \
+    $$PWD/src/jthreadconfig.h \
+    $$PWD/src/jthread.h \
+    $$PWD/src/jmutexautolock.h \
+    $$PWD/src/jmutex.h
+
+win32{
+    LIBS += -lAdvapi32
+}

+ 129 - 0
lib/common/jrtplib/src/CMakeLists.txt

@@ -0,0 +1,129 @@
+add_definitions(-DJRTPLIB_COMPILING)
+
+set (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(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)
+
+if (UNIX)
+	set (SOURCES ${SOURCES} extratransmitters/rtpfaketransmitter.cpp )
+	set (HEADERS ${HEADERS} extratransmitters/rtpfaketransmitter.h )
+else (UNIX)
+	set(CMAKE_DEBUG_POSTFIX _d)
+endif (UNIX)
+
+if (UNIX OR JRTPLIB_COMPILE_STATIC)
+	add_library(jrtplib-static STATIC ${SOURCES} ${HEADERS})
+	if (UNIX)
+		set_target_properties(jrtplib-static PROPERTIES OUTPUT_NAME jrtp)
+	else (UNIX)
+		set_target_properties(jrtplib-static PROPERTIES OUTPUT_NAME jrtplib)
+	endif(UNIX)
+	set_target_properties(jrtplib-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
+	set(JRTPLIB_INSTALLTARGETS jrtplib-static)
+	target_link_libraries(jrtplib-static ${JRTPLIB_LINK_LIBS})
+endif (UNIX OR JRTPLIB_COMPILE_STATIC)
+
+if (UNIX OR NOT JRTPLIB_COMPILE_STATIC)
+	add_library(jrtplib-shared SHARED ${SOURCES} ${HEADERS})
+	if (UNIX)
+		set_target_properties(jrtplib-shared PROPERTIES OUTPUT_NAME jrtp)
+	else (UNIX)
+		set_target_properties(jrtplib-shared PROPERTIES OUTPUT_NAME jrtplib)
+	endif(UNIX)
+	set_target_properties(jrtplib-shared PROPERTIES VERSION ${VERSION})
+	set_target_properties(jrtplib-shared PROPERTIES CLEAN_DIRECT_OUTPUT 1)
+	set(JRTPLIB_INSTALLTARGETS ${JRTPLIB_INSTALLTARGETS} jrtplib-shared)
+	target_link_libraries(jrtplib-shared ${JRTPLIB_LINK_LIBS})
+endif (UNIX OR NOT JRTPLIB_COMPILE_STATIC)
+
+apply_include_paths("${JRTPLIB_INTERNAL_INCLUDES}")
+apply_include_paths("${JRTPLIB_EXTERNAL_INCLUDES}")
+
+install(FILES ${HEADERS} DESTINATION include/jrtplib3)
+install(TARGETS ${JRTPLIB_INSTALLTARGETS} DESTINATION ${LIBRARY_INSTALL_DIR})
+

+ 2 - 0
lib/common/jrtplib/src/errcodecommand

@@ -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

+ 1726 - 0
lib/common/jrtplib/src/extratransmitters/rtpfaketransmitter.cpp

@@ -0,0 +1,1726 @@
+/*
+
+  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.
+
+  THIS HAS NOT BEEN TESTED WITH THREADS SO DON'T TRY
+
+  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.
+
+*/
+
+#include "rtpfaketransmitter.h"
+
+#include "rtprawpacket.h"
+#include "rtpipv4address.h"
+#include "rtptimeutilities.h"
+#include <stdio.h>
+
+#include <sys/socket.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
+
+#define RTPIOCTL								ioctl
+
+#ifdef RTPDEBUG
+	#include <iostream>
+#endif // RTPDEBUG
+
+#include "rtpdebug.h"
+
+#define RTPFAKETRANS_MAXPACKSIZE							65535
+#define RTPFAKETRANS_IFREQBUFSIZE							8192
+
+//#define RTPFAKETRANS_IS_MCASTADDR(x)							(((x)&0xF0000000) == 0xE0000000)
+
+/*#define RTPFAKETRANS_MCASTMEMBERSHIP(socket,type,mcastip,status)	{\
+										struct ip_mreq mreq;\
+										\
+										mreq.imr_multiaddr.s_addr = htonl(mcastip);\
+										mreq.imr_interface.s_addr = htonl(bindIP);\
+										status = setsockopt(socket,IPPROTO_IP,type,(const char *)&mreq,sizeof(struct ip_mreq));\
+									}*/
+#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
+{
+
+RTPFakeTransmitter::RTPFakeTransmitter(RTPMemoryManager *mgr ) : RTPTransmitter(mgr), destinations(mgr,RTPMEM_TYPE_CLASS_DESTINATIONLISTHASHELEMENT),acceptignoreinfo(mgr,RTPMEM_TYPE_CLASS_ACCEPTIGNOREHASHELEMENT)
+{
+	created = false;
+	init = false;
+}
+
+RTPFakeTransmitter::~RTPFakeTransmitter()
+{
+	Destroy();
+}
+
+int RTPFakeTransmitter::Init(bool tsafe)
+{
+	if (init)
+		return ERR_RTP_FAKETRANS_ALREADYINIT;
+
+    // bomb out if trying to use threads
+    if (tsafe)
+        return ERR_RTP_NOTHREADSUPPORT;
+	
+#ifdef RTP_SUPPORT_THREAD
+	threadsafe = tsafe;
+	if (threadsafe)
+	{
+		int status;
+		
+		status = mainmutex.Init();
+		if (status < 0)
+			return ERR_RTP_FAKETRANS_CANTINITMUTEX;
+		status = waitmutex.Init();
+		if (status < 0)
+			return ERR_RTP_FAKETRANS_CANTINITMUTEX;
+	}
+#else
+	if (tsafe)
+		return ERR_RTP_NOTHREADSUPPORT;
+#endif // RTP_SUPPORT_THREAD
+
+	init = true;
+	return 0;
+}
+
+int RTPFakeTransmitter::Create(size_t maximumpacketsize,const RTPTransmissionParams *transparams)
+{
+//	struct sockaddr_in addr;
+//	int status;
+
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+	
+	MAINMUTEX_LOCK
+
+	if (created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_ALREADYCREATED;
+	}
+	
+	// Obtain transmission parameters
+	
+	if (transparams == 0)
+		params = RTPNew(GetMemoryManager(),RTPMEM_TYPE_OTHER) RTPFakeTransmissionParams;
+	else
+	{
+		if (transparams->GetTransmissionProtocol() != RTPTransmitter::UserDefinedProto)
+			return ERR_RTP_FAKETRANS_ILLEGALPARAMETERS;
+		params = (RTPFakeTransmissionParams *)transparams;
+	}
+
+	// Check if portbase is even
+	//if (params->GetPortbase()%2 != 0)
+	//{
+	//	MAINMUTEX_UNLOCK
+	//	return ERR_RTP_FAKETRANS_PORTBASENOTEVEN;
+	//}
+
+	// Try to obtain local IP addresses
+
+	localIPs = params->GetLocalIPList();
+	if (localIPs.empty()) // User did not provide list of local IP addresses, calculate them
+	{
+		int status;
+		
+		if ((status = CreateLocalIPList()) < 0)
+		{
+			MAINMUTEX_UNLOCK
+			return status;
+		}
+#ifdef RTPDEBUG
+		std::cout << "Found these local IP addresses:" << std::endl;
+		
+		std::list<uint32_t>::const_iterator it;
+
+		for (it = localIPs.begin() ; it != localIPs.end() ; it++)
+		{
+			RTPIPv4Address a(*it);
+
+			std::cout << a.GetAddressString() << std::endl;
+		}
+#endif // RTPDEBUG
+	}
+
+//#ifdef RTP_SUPPORT_IPV4MULTICAST
+//	if (SetMulticastTTL(params->GetMulticastTTL()))
+//		supportsmulticasting = true;
+//	else
+//		supportsmulticasting = false;
+//#else // no multicast support enabled
+	supportsmulticasting = false;
+//#endif // RTP_SUPPORT_IPV4MULTICAST
+
+	if (maximumpacketsize > RTPFAKETRANS_MAXPACKSIZE)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_SPECIFIEDSIZETOOBIG;
+	}
+	
+	maxpacksize = maximumpacketsize;
+	portbase = params->GetPortbase();
+	multicastTTL = params->GetMulticastTTL();
+	receivemode = RTPTransmitter::AcceptAll;
+
+	localhostname = 0;
+	localhostnamelength = 0;
+
+	waitingfordata = false;
+	created = true;
+
+	MAINMUTEX_UNLOCK
+	return 0;
+}
+
+void RTPFakeTransmitter::Destroy()
+{
+	if (!init)
+		return;
+
+	MAINMUTEX_LOCK
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK;
+		return;
+	}
+
+	if (localhostname)
+	{
+		RTPDeleteByteArray(localhostname,GetMemoryManager());
+		localhostname = 0;
+		localhostnamelength = 0;
+	}
+	
+	destinations.Clear();
+#ifdef RTP_SUPPORT_IPV4MULTICAST
+//	multicastgroups.Clear();
+#endif // RTP_SUPPORT_IPV4MULTICAST
+	FlushPackets();
+	ClearAcceptIgnoreInfo();
+	localIPs.clear();
+	created = false;
+    	RTPDelete(params,GetMemoryManager());
+	
+	MAINMUTEX_UNLOCK
+}
+
+RTPTransmissionInfo *RTPFakeTransmitter::GetTransmissionInfo()
+{
+	if (!init)
+		return 0;
+
+	MAINMUTEX_LOCK
+	RTPTransmissionInfo *tinf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPTRANSMISSIONINFO) RTPFakeTransmissionInfo(localIPs, params);
+	MAINMUTEX_UNLOCK
+	return tinf;
+}
+
+void RTPFakeTransmitter::DeleteTransmissionInfo(RTPTransmissionInfo *inf)
+{
+	if (!init)
+		return;
+	RTPDelete(inf,GetMemoryManager());
+}
+
+int RTPFakeTransmitter::GetLocalHostName(uint8_t *buffer,size_t *bufferlength)
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+
+	MAINMUTEX_LOCK
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+
+	if (localhostname == 0)
+	{
+		if (localIPs.empty())
+		{
+			MAINMUTEX_UNLOCK
+			return ERR_RTP_FAKETRANS_NOLOCALIPS;
+		}
+		
+		std::list<uint32_t>::const_iterator it;
+		std::list<std::string> hostnames;
+	
+		for (it = localIPs.begin() ; it != localIPs.end() ; it++)
+		{
+			struct hostent *he;
+			uint8_t addr[4];
+			uint32_t ip = (*it);
+	
+			addr[0] = (uint8_t)((ip>>24)&0xFF);
+			addr[1] = (uint8_t)((ip>>16)&0xFF);
+			addr[2] = (uint8_t)((ip>>8)&0xFF);
+			addr[3] = (uint8_t)(ip&0xFF);
+			he = gethostbyaddr((char *)addr,4,AF_INET);
+			if (he != 0)
+			{
+				std::string hname = std::string(he->h_name);
+				hostnames.push_back(hname);
+			}
+		}
+	
+		bool found  = false;
+		
+		if (!hostnames.empty())	// try to select the most appropriate hostname
+		{
+			std::list<std::string>::const_iterator it;
+			
+			for (it = hostnames.begin() ; !found && it != hostnames.end() ; it++)
+			{
+				if ((*it).find('.') != std::string::npos)
+				{
+					found = true;
+					localhostnamelength = (*it).length();
+					localhostname = RTPNew(GetMemoryManager(),RTPMEM_TYPE_OTHER) uint8_t [localhostnamelength+1];
+					if (localhostname == 0)
+					{
+						MAINMUTEX_UNLOCK
+						return ERR_RTP_OUTOFMEM;
+					}
+					memcpy(localhostname,(*it).c_str(),localhostnamelength);
+					localhostname[localhostnamelength] = 0;
+				}
+			}
+		}
+	
+		if (!found) // use an IP address
+		{
+			uint32_t ip;
+			int len;
+			char str[16];
+			
+			it = localIPs.begin();
+			ip = (*it);
+			
+			snprintf(str,16,"%d.%d.%d.%d",(int)((ip>>24)&0xFF),(int)((ip>>16)&0xFF),(int)((ip>>8)&0xFF),(int)(ip&0xFF));
+			len = strlen(str);
+	
+			localhostnamelength = len;
+			localhostname = RTPNew(GetMemoryManager(),RTPMEM_TYPE_OTHER) uint8_t [localhostnamelength + 1];
+			if (localhostname == 0)
+			{
+				MAINMUTEX_UNLOCK
+				return ERR_RTP_OUTOFMEM;
+			}
+			memcpy(localhostname,str,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 RTPFakeTransmitter::ComesFromThisTransmitter(const RTPAddress *addr)
+{
+	if (!init)
+		return false;
+
+	if (addr == 0)
+		return false;
+	
+	MAINMUTEX_LOCK
+	
+	bool v;
+		
+	if (created && addr->GetAddressType() == RTPAddress::IPv4Address)
+	{	
+		const RTPIPv4Address *addr2 = (const RTPIPv4Address *)addr;
+		bool found = false;
+		std::list<uint32_t>::const_iterator it;
+	
+		it = localIPs.begin();
+		while (!found && it != localIPs.end())
+		{
+			if (addr2->GetIP() == *it)
+				found = true;
+			else
+				++it;
+		}
+	
+		if (!found)
+			v = false;
+		else
+		{
+			if (addr2->GetPort() == params->GetPortbase()) // check for RTP port
+				v = true;
+			else if (addr2->GetPort() == (params->GetPortbase()+1)) // check for RTCP port
+				v = true;
+			else 
+				v = false;
+		}
+	}
+	else
+		v = false;
+
+	MAINMUTEX_UNLOCK
+	return v;
+}
+
+int RTPFakeTransmitter::Poll()
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+
+	int status;
+	
+	MAINMUTEX_LOCK
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	status = FakePoll(); // poll RTP socket
+    params->SetCurrentData(NULL);
+	MAINMUTEX_UNLOCK
+	return status;
+}
+
+int RTPFakeTransmitter::WaitForIncomingData(const RTPTime &delay,bool *dataavailable)
+{
+/*	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+	
+	MAINMUTEX_LOCK
+	
+	fd_set fdset;
+	struct timeval tv;
+	
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (waitingfordata)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_ALREADYWAITING;
+	}
+	
+	FD_ZERO(&fdset);
+	FD_SET(rtpsock,&fdset);
+	FD_SET(rtcpsock,&fdset);
+	FD_SET(abortdesc[0],&fdset);
+	tv.tv_sec = delay.GetSeconds();
+	tv.tv_usec = delay.GetMicroSeconds();
+	
+	waitingfordata = true;
+	
+	WAITMUTEX_LOCK
+	MAINMUTEX_UNLOCK
+
+	if (select(FD_SETSIZE,&fdset,0,0,&tv) < 0)
+	{
+		MAINMUTEX_LOCK
+		waitingfordata = false;
+		MAINMUTEX_UNLOCK
+		WAITMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_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))
+	{
+#ifdef WIN32
+		char buf[1];
+		
+		recv(abortdesc[0],buf,1,0);
+#else 
+		unsigned char buf[1];
+
+		read(abortdesc[0],buf,1);
+#endif // WIN32
+	}
+	
+	MAINMUTEX_UNLOCK
+	WAITMUTEX_UNLOCK
+	return 0;*/
+	return ERR_RTP_FAKETRANS_WAITNOTIMPLEMENTED;
+}
+
+int RTPFakeTransmitter::AbortWait()
+{
+/*	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+	
+	MAINMUTEX_LOCK
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (!waitingfordata)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTWAITING;
+	}
+
+	AbortWaitInternal();
+	
+	MAINMUTEX_UNLOCK
+	return 0;*/
+	return 0;
+}
+
+int RTPFakeTransmitter::SendRTPData(const void *data,size_t len)	
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+
+	MAINMUTEX_LOCK
+	
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (len > maxpacksize)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_SPECIFIEDSIZETOOBIG;
+	}
+
+
+	destinations.GotoFirstElement();
+    // send to each destination
+	while (destinations.HasCurrentElement())
+	{
+        (*params->GetPacketReadyCB())(params->GetPacketReadyCBData(), (uint8_t*)data, len,
+        destinations.GetCurrentElement().GetIP_NBO(),
+        destinations.GetCurrentElement().GetRTPPort_NBO(),
+        1);
+		destinations.GotoNextElement();
+	}
+	
+	MAINMUTEX_UNLOCK
+	return 0;
+}
+
+int RTPFakeTransmitter::SendRTCPData(const void *data,size_t len)
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+
+	MAINMUTEX_LOCK
+
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (len > maxpacksize)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_SPECIFIEDSIZETOOBIG;
+	}
+
+	destinations.GotoFirstElement();
+    // send to each destination
+	while (destinations.HasCurrentElement())
+	{
+        (*params->GetPacketReadyCB())(params->GetPacketReadyCBData(), (uint8_t*)data, len,
+        destinations.GetCurrentElement().GetIP_NBO(),
+        destinations.GetCurrentElement().GetRTCPPort_NBO(), 
+        0);
+		destinations.GotoNextElement();
+	}
+	
+	MAINMUTEX_UNLOCK
+	return 0;
+}
+
+int RTPFakeTransmitter::AddDestination(const RTPAddress &addr)
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+	
+	MAINMUTEX_LOCK
+
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (addr.GetAddressType() != RTPAddress::IPv4Address)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE;
+	}
+	
+	RTPIPv4Address &address = (RTPIPv4Address &)addr;
+	RTPIPv4Destination dest(address.GetIP(),address.GetPort());
+	int status = destinations.AddElement(dest);
+
+	MAINMUTEX_UNLOCK
+	return status;
+}
+
+int RTPFakeTransmitter::DeleteDestination(const RTPAddress &addr)
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+	
+	MAINMUTEX_LOCK
+	
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (addr.GetAddressType() != RTPAddress::IPv4Address)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE;
+	}
+	
+	RTPIPv4Address &address = (RTPIPv4Address &)addr;	
+	RTPIPv4Destination dest(address.GetIP(),address.GetPort());
+	int status = destinations.DeleteElement(dest);
+	
+	MAINMUTEX_UNLOCK
+	return status;
+}
+
+void RTPFakeTransmitter::ClearDestinations()
+{
+	if (!init)
+		return;
+	
+	MAINMUTEX_LOCK
+	if (created)
+		destinations.Clear();
+	MAINMUTEX_UNLOCK
+}
+
+bool RTPFakeTransmitter::SupportsMulticasting()
+{
+	if (!init)
+		return false;
+	
+	MAINMUTEX_LOCK
+	
+	bool v;
+		
+	if (!created)
+		v = false;
+	else
+		v = supportsmulticasting;
+
+	MAINMUTEX_UNLOCK
+	return v;
+}
+
+#ifdef RTP_SUPPORT_IPV4MULTICAST
+
+int RTPFakeTransmitter::JoinMulticastGroup(const RTPAddress &addr)
+{
+// hrrm wonder how will manage to get multicast info thru to the UDPSINK
+/*	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+
+	MAINMUTEX_LOCK
+	
+	int status;
+	
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (addr.GetAddressType() != RTPAddress::IPv4Address)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE;
+	}
+	
+	const RTPIPv4Address &address = (const RTPIPv4Address &)addr;
+	uint32_t mcastIP = address.GetIP();
+	
+	if (!RTPFakeTRANS_IS_MCASTADDR(mcastIP))
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTAMULTICASTADDRESS;
+	}
+	
+	status = multicastgroups.AddElement(mcastIP);
+	if (status >= 0)
+	{
+		RTPFakeTRANS_MCASTMEMBERSHIP(rtpsock,IP_ADD_MEMBERSHIP,mcastIP,status);
+		if (status != 0)
+		{
+			multicastgroups.DeleteElement(mcastIP);
+			MAINMUTEX_UNLOCK
+			return ERR_RTP_FAKETRANS_COULDNTJOINMULTICASTGROUP;
+		}
+		RTPFakeTRANS_MCASTMEMBERSHIP(rtcpsock,IP_ADD_MEMBERSHIP,mcastIP,status);
+		if (status != 0)
+		{
+			RTPFakeTRANS_MCASTMEMBERSHIP(rtpsock,IP_DROP_MEMBERSHIP,mcastIP,status);
+			multicastgroups.DeleteElement(mcastIP);
+			MAINMUTEX_UNLOCK
+			return ERR_RTP_FAKETRANS_COULDNTJOINMULTICASTGROUP;
+		}
+	}
+	MAINMUTEX_UNLOCK	
+	return status;*/
+	return ERR_RTP_FAKETRANS_NOMULTICASTSUPPORT;
+}
+
+int RTPFakeTransmitter::LeaveMulticastGroup(const RTPAddress &addr)
+{
+    /*
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+
+	MAINMUTEX_LOCK
+	
+	int status;
+	
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (addr.GetAddressType() != RTPAddress::IPv4Address)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE;
+	}
+	
+	const RTPIPv4Address &address = (const RTPIPv4Address &)addr;
+	uint32_t mcastIP = address.GetIP();
+	
+	if (!RTPFakeTRANS_IS_MCASTADDR(mcastIP))
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTAMULTICASTADDRESS;
+	}
+	
+	status = multicastgroups.DeleteElement(mcastIP);
+	if (status >= 0)
+	{	
+		RTPFakeTRANS_MCASTMEMBERSHIP(rtpsock,IP_DROP_MEMBERSHIP,mcastIP,status);
+		RTPFakeTRANS_MCASTMEMBERSHIP(rtcpsock,IP_DROP_MEMBERSHIP,mcastIP,status);
+		status = 0;
+	}
+	
+	MAINMUTEX_UNLOCK
+	return status;
+    */
+	return ERR_RTP_FAKETRANS_NOMULTICASTSUPPORT;
+}
+
+void RTPFakeTransmitter::LeaveAllMulticastGroups()
+{
+/*	if (!init)
+		return;
+	
+	MAINMUTEX_LOCK
+	if (created)
+	{
+		multicastgroups.GotoFirstElement();
+		while (multicastgroups.HasCurrentElement())
+		{
+			uint32_t mcastIP;
+			int status = 0;
+
+			mcastIP = multicastgroups.GetCurrentElement();
+			RTPFakeTRANS_MCASTMEMBERSHIP(rtpsock,IP_DROP_MEMBERSHIP,mcastIP,status);
+			RTPFakeTRANS_MCASTMEMBERSHIP(rtcpsock,IP_DROP_MEMBERSHIP,mcastIP,status);
+			multicastgroups.GotoNextElement();
+		}
+		multicastgroups.Clear();
+	}
+	MAINMUTEX_UNLOCK*/
+}
+
+#else // no multicast support
+
+int RTPFakeTransmitter::JoinMulticastGroup(const RTPAddress &addr)
+{
+	return ERR_RTP_FAKETRANS_NOMULTICASTSUPPORT;
+}
+
+int RTPFakeTransmitter::LeaveMulticastGroup(const RTPAddress &addr)
+{
+	return ERR_RTP_FAKETRANS_NOMULTICASTSUPPORT;
+}
+
+void RTPFakeTransmitter::LeaveAllMulticastGroups()
+{
+}
+
+#endif // RTP_SUPPORT_IPV4MULTICAST
+
+int RTPFakeTransmitter::SetReceiveMode(RTPTransmitter::ReceiveMode m)
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+	
+	MAINMUTEX_LOCK
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (m != receivemode)
+	{
+		receivemode = m;
+		acceptignoreinfo.Clear();
+	}
+	MAINMUTEX_UNLOCK
+	return 0;
+}
+
+int RTPFakeTransmitter::AddToIgnoreList(const RTPAddress &addr)
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+
+	MAINMUTEX_LOCK
+	
+	int status;
+
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (addr.GetAddressType() != RTPAddress::IPv4Address)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE;
+	}
+	if (receivemode != RTPTransmitter::IgnoreSome)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_DIFFERENTRECEIVEMODE;
+	}
+	
+	const RTPIPv4Address &address = (const RTPIPv4Address &)addr;
+	status = ProcessAddAcceptIgnoreEntry(address.GetIP(),address.GetPort());
+	
+	MAINMUTEX_UNLOCK
+	return status;
+}
+
+int RTPFakeTransmitter::DeleteFromIgnoreList(const RTPAddress &addr)
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+	
+	MAINMUTEX_LOCK
+	
+	int status;
+	
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (addr.GetAddressType() != RTPAddress::IPv4Address)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE;
+	}
+	if (receivemode != RTPTransmitter::IgnoreSome)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_DIFFERENTRECEIVEMODE;
+	}
+	
+	const RTPIPv4Address &address = (const RTPIPv4Address &)addr;	
+	status = ProcessDeleteAcceptIgnoreEntry(address.GetIP(),address.GetPort());
+
+	MAINMUTEX_UNLOCK
+	return status;
+}
+
+void RTPFakeTransmitter::ClearIgnoreList()
+{
+	if (!init)
+		return;
+	
+	MAINMUTEX_LOCK
+	if (created && receivemode == RTPTransmitter::IgnoreSome)
+		ClearAcceptIgnoreInfo();
+	MAINMUTEX_UNLOCK
+}
+
+int RTPFakeTransmitter::AddToAcceptList(const RTPAddress &addr)
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+	
+	MAINMUTEX_LOCK
+	
+	int status;
+	
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (addr.GetAddressType() != RTPAddress::IPv4Address)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE;
+	}
+	if (receivemode != RTPTransmitter::AcceptSome)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_DIFFERENTRECEIVEMODE;
+	}
+	
+	const RTPIPv4Address &address = (const RTPIPv4Address &)addr;
+	status = ProcessAddAcceptIgnoreEntry(address.GetIP(),address.GetPort());
+
+	MAINMUTEX_UNLOCK
+	return status;
+}
+
+int RTPFakeTransmitter::DeleteFromAcceptList(const RTPAddress &addr)
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+	
+	MAINMUTEX_LOCK
+	
+	int status;
+	
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (addr.GetAddressType() != RTPAddress::IPv4Address)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE;
+	}
+	if (receivemode != RTPTransmitter::AcceptSome)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_DIFFERENTRECEIVEMODE;
+	}
+	
+	const RTPIPv4Address &address = (const RTPIPv4Address &)addr;
+	status = ProcessDeleteAcceptIgnoreEntry(address.GetIP(),address.GetPort());
+
+	MAINMUTEX_UNLOCK
+	return status;
+}
+
+void RTPFakeTransmitter::ClearAcceptList()
+{
+	if (!init)
+		return;
+	
+	MAINMUTEX_LOCK
+	if (created && receivemode == RTPTransmitter::AcceptSome)
+		ClearAcceptIgnoreInfo();
+	MAINMUTEX_UNLOCK
+}
+
+int RTPFakeTransmitter::SetMaximumPacketSize(size_t s)	
+{
+	if (!init)
+		return ERR_RTP_FAKETRANS_NOTINIT;
+	
+	MAINMUTEX_LOCK
+	if (!created)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_NOTCREATED;
+	}
+	if (s > RTPFAKETRANS_MAXPACKSIZE)
+	{
+		MAINMUTEX_UNLOCK
+		return ERR_RTP_FAKETRANS_SPECIFIEDSIZETOOBIG;
+	}
+	maxpacksize = s;
+	MAINMUTEX_UNLOCK
+	return 0;
+}
+
+bool RTPFakeTransmitter::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 *RTPFakeTransmitter::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...
+
+#ifdef RTP_SUPPORT_IPV4MULTICAST
+bool RTPFakeTransmitter::SetMulticastTTL(uint8_t ttl)
+{
+/*	int ttl2,status;
+
+	ttl2 = (int)ttl;
+	status = setsockopt(rtpsock,IPPROTO_IP,IP_MULTICAST_TTL,(const char *)&ttl2,sizeof(int));
+	if (status != 0)
+		return false;
+	status = setsockopt(rtcpsock,IPPROTO_IP,IP_MULTICAST_TTL,(const char *)&ttl2,sizeof(int));
+	if (status != 0)
+		return false;
+	return true;*/
+	return true;
+}
+#endif // RTP_SUPPORT_IPV4MULTICAST
+
+void RTPFakeTransmitter::FlushPackets()
+{
+	std::list<RTPRawPacket*>::const_iterator it;
+
+	for (it = rawpacketlist.begin() ; it != rawpacketlist.end() ; ++it)
+		RTPDelete(*it,GetMemoryManager());
+	rawpacketlist.clear();
+}
+
+int RTPFakeTransmitter::FakePoll()
+{
+    uint8_t *data = NULL;
+    int data_len = 0;
+    uint32_t sourceaddr;
+    uint16_t sourceport;
+    bool rtp;
+    bool acceptdata;
+
+    RTPTime curtime = RTPTime::CurrentTime();
+
+    data = params->GetCurrentData();
+    data_len = params->GetCurrentDataLen();
+    rtp = params->GetCurrentDataType();
+    sourceaddr = params->GetCurrentDataAddr();
+    sourceport = params->GetCurrentDataPort();
+    // lets make sure we got something
+    if (data == NULL || data_len <= 0)
+    {
+        return 0;
+    }
+
+    // let's make a RTPIPv4Address
+    RTPIPv4Address *addr = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPADDRESS) RTPIPv4Address(sourceaddr, sourceport);
+    if (addr == 0)
+    {
+        return ERR_RTP_OUTOFMEM;
+    }
+
+    // ok we got the src addr, now this should be the actual packet
+    uint8_t *datacopy;
+    datacopy = RTPNew(GetMemoryManager(),(rtp)?RTPMEM_TYPE_BUFFER_RECEIVEDRTPPACKET:RTPMEM_TYPE_BUFFER_RECEIVEDRTCPPACKET) uint8_t[data_len];
+    if (datacopy == 0)
+    {
+        RTPDelete(addr,GetMemoryManager());
+        return ERR_RTP_OUTOFMEM;
+    }
+    memcpy(datacopy, data, data_len);
+
+    // got data, process it
+    if (receivemode == RTPTransmitter::AcceptAll)
+        acceptdata = true;
+    else
+        acceptdata = ShouldAcceptData(addr->GetIP(),addr->GetPort());
+
+    if (acceptdata)
+    {
+        // adding packet to queue
+        RTPRawPacket *pack;
+
+        pack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPRAWPACKET) RTPRawPacket(datacopy,data_len,addr,curtime,rtp,GetMemoryManager());
+
+        if (pack == 0)
+        {
+            RTPDelete(addr,GetMemoryManager());
+            return ERR_RTP_OUTOFMEM;
+        }
+        rawpacketlist.push_back(pack);	
+    }
+    return 0;
+}
+
+int RTPFakeTransmitter::ProcessAddAcceptIgnoreEntry(uint32_t ip,uint16_t port)
+{
+	acceptignoreinfo.GotoElement(ip);
+	if (acceptignoreinfo.HasCurrentElement()) // An entry for this IP address already exists
+	{
+		PortInfo *portinf = acceptignoreinfo.GetCurrentElement();
+		
+		if (port == 0) // select all ports
+		{
+			portinf->all = true;
+			portinf->portlist.clear();
+		}
+		else if (!portinf->all)
+		{
+			std::list<uint16_t>::const_iterator it,begin,end;
+
+			begin = portinf->portlist.begin();
+			end = portinf->portlist.end();
+			for (it = begin ; it != end ; it++)
+			{
+				if (*it == port) // already in list
+					return 0;
+			}
+			portinf->portlist.push_front(port);
+		}
+	}
+	else // got to create an entry for this IP address
+	{
+		PortInfo *portinf;
+		int status;
+		
+		portinf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_ACCEPTIGNOREPORTINFO) PortInfo();
+		if (port == 0) // select all ports
+			portinf->all = true;
+		else
+			portinf->portlist.push_front(port);
+		
+		status = acceptignoreinfo.AddElement(ip,portinf);
+		if (status < 0)
+		{
+			RTPDelete(portinf,GetMemoryManager());
+			return status;
+		}
+	}
+
+	return 0;
+}
+
+void RTPFakeTransmitter::ClearAcceptIgnoreInfo()
+{
+	acceptignoreinfo.GotoFirstElement();
+	while (acceptignoreinfo.HasCurrentElement())
+	{
+		PortInfo *inf;
+
+		inf = acceptignoreinfo.GetCurrentElement();
+		RTPDelete(inf,GetMemoryManager());
+		acceptignoreinfo.GotoNextElement();
+	}
+	acceptignoreinfo.Clear();
+}
+	
+int RTPFakeTransmitter::ProcessDeleteAcceptIgnoreEntry(uint32_t ip,uint16_t port)
+{
+	acceptignoreinfo.GotoElement(ip);
+	if (!acceptignoreinfo.HasCurrentElement())
+		return ERR_RTP_FAKETRANS_NOSUCHENTRY;
+	
+	PortInfo *inf;
+
+	inf = acceptignoreinfo.GetCurrentElement();
+	if (port == 0) // delete all entries
+	{
+		inf->all = false;
+		inf->portlist.clear();
+	}
+	else // a specific port was selected
+	{
+		if (inf->all) // currently, all ports are selected. Add the one to remove to the list
+		{
+			// we have to check if the list doesn't contain the port already
+			std::list<uint16_t>::const_iterator it,begin,end;
+
+			begin = inf->portlist.begin();
+			end = inf->portlist.end();
+			for (it = begin ; it != end ; it++)
+			{
+				if (*it == port) // already in list: this means we already deleted the entry
+					return ERR_RTP_FAKETRANS_NOSUCHENTRY;
+			}
+			inf->portlist.push_front(port);
+		}
+		else // check if we can find the port in the list
+		{
+			std::list<uint16_t>::iterator it,begin,end;
+			
+			begin = inf->portlist.begin();
+			end = inf->portlist.end();
+			for (it = begin ; it != end ; ++it)
+			{
+				if (*it == port) // found it!
+				{
+					inf->portlist.erase(it);
+					return 0;
+				}
+			}
+			// didn't find it
+			return ERR_RTP_FAKETRANS_NOSUCHENTRY;			
+		}
+	}
+	return 0;
+}
+
+bool RTPFakeTransmitter::ShouldAcceptData(uint32_t srcip,uint16_t srcport)
+{
+	if (receivemode == RTPTransmitter::AcceptSome)
+	{
+		PortInfo *inf;
+
+		acceptignoreinfo.GotoElement(srcip);
+		if (!acceptignoreinfo.HasCurrentElement())
+			return false;
+		
+		inf = acceptignoreinfo.GetCurrentElement();
+		if (!inf->all) // only accept the ones in the list
+		{
+			std::list<uint16_t>::const_iterator it,begin,end;
+
+			begin = inf->portlist.begin();
+			end = inf->portlist.end();
+			for (it = begin ; it != end ; it++)
+			{
+				if (*it == srcport)
+					return true;
+			}
+			return false;
+		}
+		else // accept all, except the ones in the list
+		{
+			std::list<uint16_t>::const_iterator it,begin,end;
+
+			begin = inf->portlist.begin();
+			end = inf->portlist.end();
+			for (it = begin ; it != end ; it++)
+			{
+				if (*it == srcport)
+					return false;
+			}
+			return true;
+		}
+	}
+	else // IgnoreSome
+	{
+		PortInfo *inf;
+
+		acceptignoreinfo.GotoElement(srcip);
+		if (!acceptignoreinfo.HasCurrentElement())
+			return true;
+		
+		inf = acceptignoreinfo.GetCurrentElement();
+		if (!inf->all) // ignore the ports in the list
+		{
+			std::list<uint16_t>::const_iterator it,begin,end;
+
+			begin = inf->portlist.begin();
+			end = inf->portlist.end();
+			for (it = begin ; it != end ; it++)
+			{
+				if (*it == srcport)
+					return false;
+			}
+			return true;
+		}
+		else // ignore all, except the ones in the list
+		{
+			std::list<uint16_t>::const_iterator it,begin,end;
+
+			begin = inf->portlist.begin();
+			end = inf->portlist.end();
+			for (it = begin ; it != end ; it++)
+			{
+				if (*it == srcport)
+					return true;
+			}
+			return false;
+		}
+	}
+	return true;
+}
+
+#ifdef WIN32
+
+int RTPFakeTransmitter::CreateAbortDescriptors()
+{
+    // no need for these no more
+/*
+	SOCKET listensock;
+	int size;
+	struct sockaddr_in addr;
+
+	listensock = socket(PF_INET,SOCK_STREAM,0);
+	if (listensock == RTPSOCKERR)
+		return ERR_RTP_FAKETRANS_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_FAKETRANS_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_FAKETRANS_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_FAKETRANS_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_FAKETRANS_CANTCREATEABORTDESCRIPTORS;
+	}
+
+	if (listen(listensock,1) != 0)
+	{
+		RTPCLOSE(listensock);
+		RTPCLOSE(abortdesc[0]);
+		return ERR_RTP_FAKETRANS_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_FAKETRANS_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_FAKETRANS_CANTCREATEABORTDESCRIPTORS;
+	}
+
+	// okay, got the connection, close the listening socket
+
+	RTPCLOSE(listensock);
+	return 0;*/
+}
+
+void RTPFakeTransmitter::DestroyAbortDescriptors()
+{
+//	RTPCLOSE(abortdesc[0]);
+//	RTPCLOSE(abortdesc[1]);
+}
+
+#else // in a non winsock environment we can use pipes
+
+int RTPFakeTransmitter::CreateAbortDescriptors()
+{
+//	if (pipe(abortdesc) < 0)
+//		return ERR_RTP_FAKETRANS_CANTCREATEPIPE;
+//	return 0;
+	return 0;
+}
+
+void RTPFakeTransmitter::DestroyAbortDescriptors()
+{
+//	close(abortdesc[0]);
+//	close(abortdesc[1]);
+}
+
+#endif // WIN32
+
+int RTPFakeTransmitter::CreateLocalIPList()
+{
+	 // first try to obtain the list from the network interface info
+
+	if (!GetLocalIPList_Interfaces())
+	{
+		// If this fails, we'll have to depend on DNS info
+		GetLocalIPList_DNS();
+	}
+	AddLoopbackAddress();
+	return 0;
+}
+
+//#ifdef WIN32
+
+bool RTPFakeTransmitter::GetLocalIPList_Interfaces()
+{
+	// REMINDER: got to find out how to do this
+	return false;
+}
+/*
+#else // use ioctl
+
+bool RTPFakeTransmitter::GetLocalIPList_Interfaces()
+{
+	int status;
+	char buffer[RTPFakeTRANS_IFREQBUFSIZE];
+	struct ifconf ifc;
+	struct ifreq *ifr;
+	struct sockaddr *sa;
+	char *startptr,*endptr;
+	int remlen;
+	
+	ifc.ifc_len = RTPFakeTRANS_IFREQBUFSIZE;
+	ifc.ifc_buf = buffer;
+	status = ioctl(rtpsock,SIOCGIFCONF,&ifc);
+	if (status < 0)
+		return false;
+	
+	startptr = (char *)ifc.ifc_req;
+	endptr = startptr + ifc.ifc_len;
+	remlen = ifc.ifc_len;
+	while((startptr < endptr) && remlen >= (int)sizeof(struct ifreq))
+	{
+		ifr = (struct ifreq *)startptr;
+		sa = &(ifr->ifr_addr);
+#ifdef RTP_HAVE_SOCKADDR_LEN
+		if (sa->sa_len <= sizeof(struct sockaddr))
+		{
+			if (sa->sa_len == sizeof(struct sockaddr_in) && sa->sa_family == PF_INET)
+			{
+				uint32_t ip;
+				struct sockaddr_in *addr = (struct sockaddr_in *)sa;
+				
+				ip = ntohl(addr->sin_addr.s_addr);
+				localIPs.push_back(ip);
+			}
+			remlen -= sizeof(struct ifreq);
+			startptr += sizeof(struct ifreq);
+		}
+		else
+		{
+			int l = sa->sa_len-sizeof(struct sockaddr)+sizeof(struct ifreq);
+			
+			remlen -= l;
+			startptr += l;
+		}
+#else // don't have sa_len in struct sockaddr
+		if (sa->sa_family == PF_INET)
+		{
+			uint32_t ip;
+			struct sockaddr_in *addr = (struct sockaddr_in *)sa;
+		
+			ip = ntohl(addr->sin_addr.s_addr);
+			localIPs.push_back(ip);
+		}
+		remlen -= sizeof(struct ifreq);
+		startptr += sizeof(struct ifreq);
+	
+#endif // RTP_HAVE_SOCKADDR_LEN
+	}
+
+	if (localIPs.empty())
+		return false;
+	return true;
+}
+
+#endif // WIN32
+*/
+void RTPFakeTransmitter::GetLocalIPList_DNS()
+{
+	struct hostent *he;
+	char name[1024];
+	uint32_t ip;
+	bool done;
+	int i,j;
+
+	gethostname(name,1023);
+	name[1023] = 0;
+	he = gethostbyname(name);
+	if (he == 0)
+		return;
+	
+	ip = 0;
+	i = 0;
+	done = false;
+	while (!done)
+	{
+		if (he->h_addr_list[i] == NULL)
+			done = true;
+		else
+		{
+			ip = 0;
+			for (j = 0 ; j < 4 ; j++)
+				ip |= ((uint32_t)((unsigned char)he->h_addr_list[i][j])<<((3-j)*8));
+			localIPs.push_back(ip);
+			i++;
+		}
+	}
+}
+
+void RTPFakeTransmitter::AbortWaitInternal()
+{
+/*#ifdef WIN32
+	send(abortdesc[1],"*",1,0);
+#else
+	write(abortdesc[1],"*",1);
+#endif // WIN32*/
+}
+
+void RTPFakeTransmitter::AddLoopbackAddress()
+{
+	uint32_t loopbackaddr = (((uint32_t)127)<<24)|((uint32_t)1);
+	std::list<uint32_t>::const_iterator it;
+	bool found = false;
+	
+	for (it = localIPs.begin() ; !found && it != localIPs.end() ; it++)
+	{
+		if (*it == loopbackaddr)
+			found = true;
+	}
+
+	if (!found)
+		localIPs.push_back(loopbackaddr);
+}
+
+#ifdef RTPDEBUG
+void RTPFakeTransmitter::Dump()
+{
+	if (!init)
+		std::cout << "Not initialized" << std::endl;
+	else
+	{
+		MAINMUTEX_LOCK
+	
+		if (!created)
+			std::cout << "Not created" << std::endl;
+		else
+		{
+			char str[16];
+			uint32_t ip;
+			std::list<uint32_t>::const_iterator it;
+			
+			std::cout << "Portbase:                       " << params->GetPortbase() << std::endl;
+			std::cout << "Local IP addresses:" << std::endl;
+			for (it = localIPs.begin() ; it != localIPs.end() ; it++)
+			{
+				ip = (*it);
+				snprintf(str,16,"%d.%d.%d.%d",(int)((ip>>24)&0xFF),(int)((ip>>16)&0xFF),(int)((ip>>8)&0xFF),(int)(ip&0xFF));
+				std::cout << "    " << str << std::endl;
+			}
+//			std::cout << "Multicast TTL:                  " << (int)multicastTTL << std::endl;
+			std::cout << "Receive mode:                   ";
+			switch (receivemode)
+			{
+			case RTPTransmitter::AcceptAll:
+				std::cout << "Accept all";
+				break;
+			case RTPTransmitter::AcceptSome:
+				std::cout << "Accept some";
+				break;
+			case RTPTransmitter::IgnoreSome:
+				std::cout << "Ignore some";
+			}
+			std::cout << std::endl;
+			if (receivemode != RTPTransmitter::AcceptAll)
+			{
+				acceptignoreinfo.GotoFirstElement();
+				while(acceptignoreinfo.HasCurrentElement())
+				{
+					ip = acceptignoreinfo.GetCurrentKey();
+					snprintf(str,16,"%d.%d.%d.%d",(int)((ip>>24)&0xFF),(int)((ip>>16)&0xFF),(int)((ip>>8)&0xFF),(int)(ip&0xFF));
+					PortInfo *pinfo = acceptignoreinfo.GetCurrentElement();
+					std::cout << "    " << str << ": ";
+					if (pinfo->all)
+					{
+						std::cout << "All ports";
+						if (!pinfo->portlist.empty())
+							std::cout << ", except ";
+					}
+					
+					std::list<uint16_t>::const_iterator it;
+					
+					for (it = pinfo->portlist.begin() ; it != pinfo->portlist.end() ; )
+					{
+						std::cout << (*it);
+						it++;
+						if (it != pinfo->portlist.end())
+							std::cout << ", ";
+					}
+					std::cout << std::endl;
+				}
+			}
+			
+			std::cout << "Local host name:                ";
+			if (localhostname == 0)
+				std::cout << "Not set";
+			else
+				std::cout << localhostname;
+			std::cout << std::endl;
+
+			std::cout << "List of destinations:           ";
+			destinations.GotoFirstElement();
+			if (destinations.HasCurrentElement())
+			{
+				std::cout << std::endl;
+				do
+				{
+					std::cout << "    " << destinations.GetCurrentElement().GetDestinationString() << std::endl;
+					destinations.GotoNextElement();
+				} while (destinations.HasCurrentElement());
+			}
+			else
+				std::cout << "Empty" << std::endl;
+		
+			std::cout << "Supports multicasting:          " << ((supportsmulticasting)?"Yes":"No") << std::endl;
+#ifdef RTP_SUPPORT_IPV4MULTICAST
+/*			std::cout << "List of multicast groups:       ";
+			multicastgroups.GotoFirstElement();
+			if (multicastgroups.HasCurrentElement())
+			{
+				std::cout << std::endl;
+				do
+				{
+					ip = multicastgroups.GetCurrentElement();
+					snprintf(str,16,"%d.%d.%d.%d",(int)((ip>>24)&0xFF),(int)((ip>>16)&0xFF),(int)((ip>>8)&0xFF),(int)(ip&0xFF));
+					std::cout << "    " << str << std::endl;
+					multicastgroups.GotoNextElement();
+				} while (multicastgroups.HasCurrentElement());
+			}
+			else
+				std::cout << "Empty" << std::endl;*/
+#endif // RTP_SUPPORT_IPV4MULTICAST
+			
+			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
+

+ 247 - 0
lib/common/jrtplib/src/extratransmitters/rtpfaketransmitter.h

@@ -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
+

+ 87 - 0
lib/common/jrtplib/src/jmutex.cpp

@@ -0,0 +1,87 @@
+/*
+
+    This file is a part of the JThread package, which contains some object-
+    oriented thread wrappers for different thread implementations.
+
+    Copyright (c) 2000-2011  Jori Liesenborgs (jori.liesenborgs@gmail.com)
+
+    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 "jmutex.h"
+
+namespace jthread
+{
+
+JMutex::JMutex()
+{
+	initialized = false;
+}
+
+JMutex::~JMutex()
+{
+	if (initialized)
+#ifdef JTHREAD_CONFIG_JMUTEXCRITICALSECTION
+		DeleteCriticalSection(&mutex);
+#else
+		CloseHandle(mutex);
+#endif // JTHREAD_CONFIG_JMUTEXCRITICALSECTION
+}
+
+int JMutex::Init()
+{
+	if (initialized)
+		return ERR_JMUTEX_ALREADYINIT;
+#ifdef JTHREAD_CONFIG_JMUTEXCRITICALSECTION
+	InitializeCriticalSection(&mutex);
+#else
+	mutex = CreateMutex(NULL,FALSE,NULL);
+	if (mutex == NULL)
+		return ERR_JMUTEX_CANTCREATEMUTEX;
+#endif // JTHREAD_CONFIG_JMUTEXCRITICALSECTION
+	initialized = true;
+	return 0;
+}
+
+int JMutex::Lock()
+{
+	if (!initialized)
+		return ERR_JMUTEX_NOTINIT;
+#ifdef JTHREAD_CONFIG_JMUTEXCRITICALSECTION
+	EnterCriticalSection(&mutex);
+#else
+	WaitForSingleObject(mutex,INFINITE);
+#endif // JTHREAD_CONFIG_JMUTEXCRITICALSECTION
+	return 0;
+}
+
+int JMutex::Unlock()
+{
+	if (!initialized)
+		return ERR_JMUTEX_NOTINIT;
+#ifdef JTHREAD_CONFIG_JMUTEXCRITICALSECTION
+	LeaveCriticalSection(&mutex);
+#else
+	ReleaseMutex(mutex);
+#endif // JTHREAD_CONFIG_JMUTEXCRITICALSECTION
+	return 0;
+}
+
+} // end namespace

+ 75 - 0
lib/common/jrtplib/src/jmutex.h

@@ -0,0 +1,75 @@
+/*
+
+    This file is a part of the JThread package, which contains some object-
+    oriented thread wrappers for different thread implementations.
+
+    Copyright (c) 2000-2011  Jori Liesenborgs (jori.liesenborgs@gmail.com)
+
+    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 JTHREAD_JMUTEX_H
+
+#define JTHREAD_JMUTEX_H
+
+#include "jthreadconfig.h"
+#ifdef JTHREAD_CONFIG_WIN32THREADS
+	#ifndef _WIN32_WCE
+		#include <process.h>
+	#endif // _WIN32_WCE
+	#include <winsock2.h>
+	#include <windows.h>
+#else // using pthread
+	#include <pthread.h>
+#endif // JTHREAD_CONFIG_WIN32THREADS
+
+#define ERR_JMUTEX_ALREADYINIT						-1
+#define ERR_JMUTEX_NOTINIT						-2
+#define ERR_JMUTEX_CANTCREATEMUTEX					-3
+
+namespace jthread
+{
+
+class JTHREAD_IMPORTEXPORT JMutex
+{
+public:
+	JMutex();
+	~JMutex();
+	int Init();
+	int Lock();
+	int Unlock();
+	bool IsInitialized() 						{ return initialized; }
+private:
+#ifdef JTHREAD_CONFIG_WIN32THREADS
+#ifdef JTHREAD_CONFIG_JMUTEXCRITICALSECTION
+	CRITICAL_SECTION mutex;
+#else // Use standard mutex
+	HANDLE mutex;
+#endif // JTHREAD_CONFIG_JMUTEXCRITICALSECTION
+#else // pthread mutex
+	pthread_mutex_t mutex;
+#endif // JTHREAD_CONFIG_WIN32THREADS
+	bool initialized;
+};
+
+} // end namespace
+
+#endif // JTHREAD_JMUTEX_H
+

+ 50 - 0
lib/common/jrtplib/src/jmutexautolock.h

@@ -0,0 +1,50 @@
+/*
+
+    This file is a part of the JThread package, which contains some object-
+    oriented thread wrappers for different thread implementations.
+
+    Copyright (c) 2000-2011  Jori Liesenborgs (jori.liesenborgs@gmail.com)
+
+    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 JTHREAD_JMUTEXAUTOLOCK_H
+
+#define JTHREAD_JMUTEXAUTOLOCK_H
+
+#include "jthreadconfig.h"
+#include "jmutex.h"
+
+namespace jthread
+{
+
+class JTHREAD_IMPORTEXPORT JMutexAutoLock
+{
+public:
+	JMutexAutoLock(JMutex &m) : mutex(m)						{ mutex.Lock(); }
+	~JMutexAutoLock()								{ mutex.Unlock(); }
+private:
+	JMutex &mutex;
+};
+
+} // end namespace
+
+#endif // JTHREAD_JMUTEXAUTOLOCK_H
+

+ 182 - 0
lib/common/jrtplib/src/jthread.cpp

@@ -0,0 +1,182 @@
+/*
+
+    This file is a part of the JThread package, which contains some object-
+    oriented thread wrappers for different thread implementations.
+
+    Copyright (c) 2000-2011  Jori Liesenborgs (jori.liesenborgs@gmail.com)
+
+    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 "jthread.h"
+#include "jmutexautolock.h"
+
+#ifndef _WIN32_WCE
+	#include <process.h>
+#endif // _WIN32_WCE
+
+namespace jthread
+{
+
+JThread::JThread()
+{
+	retval = NULL;
+	mutexinit = false;
+	running = false;
+}
+
+JThread::~JThread()
+{
+	Kill();
+}
+
+int JThread::Start()
+{
+	if (!mutexinit)
+	{
+		if (!runningmutex.IsInitialized())
+		{
+			if (runningmutex.Init() < 0)
+				return ERR_JTHREAD_CANTINITMUTEX;
+		}
+		if (!continuemutex.IsInitialized())
+		{
+			if (continuemutex.Init() < 0)
+				return ERR_JTHREAD_CANTINITMUTEX;
+		}
+		if (!continuemutex2.IsInitialized())
+		{
+			if (continuemutex2.Init() < 0)
+				return ERR_JTHREAD_CANTINITMUTEX;
+		}		mutexinit = true;
+	}
+	
+	runningmutex.Lock();
+	if (running)
+	{
+		runningmutex.Unlock();
+		return ERR_JTHREAD_ALREADYRUNNING;
+	}
+	runningmutex.Unlock();
+	
+	continuemutex.Lock();
+#ifndef _WIN32_WCE
+	threadhandle = (HANDLE)_beginthreadex(NULL,0,TheThread,this,0,&threadid);
+#else
+	threadhandle = CreateThread(NULL,0,TheThread,this,0,&threadid);
+#endif // _WIN32_WCE
+	if (threadhandle == NULL)
+	{
+		continuemutex.Unlock();
+		return ERR_JTHREAD_CANTSTARTTHREAD;
+	}
+	
+	/* Wait until 'running' is set */
+
+	runningmutex.Lock();			
+	while (!running)
+	{
+		runningmutex.Unlock();
+		Sleep(1);
+		runningmutex.Lock();
+	}
+	runningmutex.Unlock();
+	
+	continuemutex.Unlock();
+	
+	continuemutex2.Lock();
+	continuemutex2.Unlock();
+		
+	return 0;
+}
+
+int JThread::Kill()
+{
+	runningmutex.Lock();			
+	if (!running)
+	{
+		runningmutex.Unlock();
+		return ERR_JTHREAD_NOTRUNNING;
+	}
+	TerminateThread(threadhandle,0);
+	CloseHandle(threadhandle);
+	running = false;
+	runningmutex.Unlock();
+	return 0;
+}
+
+bool JThread::IsRunning()
+{
+	bool r;
+	
+	runningmutex.Lock();			
+	r = running;
+	runningmutex.Unlock();
+	return r;
+}
+
+void *JThread::GetReturnValue()
+{
+	JMutexAutoLock autolock(runningmutex);
+	void *val;
+	
+	if (running)
+		val = NULL;
+	else
+		val = retval;
+	return val;
+}
+
+#ifndef _WIN32_WCE
+UINT __stdcall JThread::TheThread(void *param)
+#else
+DWORD WINAPI JThread::TheThread(void *param)
+#endif // _WIN32_WCE
+{
+	JThread *jthread;
+	void *ret;
+
+	jthread = (JThread *)param;
+	
+	jthread->continuemutex2.Lock();
+	jthread->runningmutex.Lock();
+	jthread->running = true;
+	jthread->runningmutex.Unlock();
+	
+	jthread->continuemutex.Lock();
+	jthread->continuemutex.Unlock();
+	
+	ret = jthread->Thread();
+	
+	jthread->runningmutex.Lock();
+	jthread->running = false;
+	jthread->retval = ret;
+	CloseHandle(jthread->threadhandle);
+	jthread->runningmutex.Unlock();
+	return 0;		
+}
+
+void JThread::ThreadStarted()
+{
+	continuemutex2.Unlock();
+}
+
+} // end namespace
+

+ 83 - 0
lib/common/jrtplib/src/jthread.h

@@ -0,0 +1,83 @@
+/*
+
+    This file is a part of the JThread package, which contains some object-
+    oriented thread wrappers for different thread implementations.
+
+    Copyright (c) 2000-2011  Jori Liesenborgs (jori.liesenborgs@gmail.com)
+
+    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 JTHREAD_JTHREAD_H
+
+#define JTHREAD_JTHREAD_H
+
+#include "jthreadconfig.h"
+#include "jmutex.h"
+
+#define ERR_JTHREAD_CANTINITMUTEX						-1
+#define ERR_JTHREAD_CANTSTARTTHREAD						-2
+#define ERR_JTHREAD_THREADFUNCNOTSET						-3
+#define ERR_JTHREAD_NOTRUNNING							-4
+#define ERR_JTHREAD_ALREADYRUNNING						-5
+
+namespace jthread
+{
+
+class JTHREAD_IMPORTEXPORT JThread
+{
+public:
+	JThread();
+	virtual ~JThread();
+	int Start();
+	int Kill();
+	virtual void *Thread() = 0;
+	bool IsRunning();
+	void *GetReturnValue();
+protected:
+	void ThreadStarted();
+private:
+
+#ifdef JTHREAD_CONFIG_WIN32THREADS
+#ifdef _WIN32_WCE
+	DWORD threadid;
+	static DWORD WINAPI TheThread(void *param);
+#else
+	static UINT __stdcall TheThread(void *param);
+	UINT threadid;
+#endif // _WIN32_WCE
+	HANDLE threadhandle;
+#else // pthread type threads
+	static void *TheThread(void *param);
+	
+	pthread_t threadid;
+#endif // JTHREAD_CONFIG_WIN32THREADS
+	void *retval;
+	bool running;
+	
+	JMutex runningmutex;
+	JMutex continuemutex,continuemutex2;
+	bool mutexinit;
+};
+
+} // end namespace
+
+#endif // JTHREAD_JTHREAD_H
+

+ 45 - 0
lib/common/jrtplib/src/jthreadconfig.h

@@ -0,0 +1,45 @@
+/*
+
+    This file is a part of the JThread package, which contains some object-
+    oriented thread wrappers for different thread implementations.
+
+    Copyright (c) 2000-2011  Jori Liesenborgs (jori.liesenborgs@gmail.com)
+
+    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 JTHREADCONFIG_H
+
+#define JTHREADCONFIG_H
+
+#define JTHREAD_IMPORT 
+#define JTHREAD_EXPORT 
+#ifdef JTHREAD_COMPILING
+	#define JTHREAD_IMPORTEXPORT JTHREAD_EXPORT
+#else
+	#define JTHREAD_IMPORTEXPORT JTHREAD_IMPORT
+#endif // JTHREAD_COMPILING
+
+#define JTHREAD_CONFIG_WIN32THREADS
+
+// Using standard Win32 mutex
+
+#endif // JTHREADCONFIG_H
+

+ 45 - 0
lib/common/jrtplib/src/jthreadconfig.h.in

@@ -0,0 +1,45 @@
+/*
+
+    This file is a part of the JThread package, which contains some object-
+    oriented thread wrappers for different thread implementations.
+
+    Copyright (c) 2000-2011  Jori Liesenborgs (jori.liesenborgs@gmail.com)
+
+    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 JTHREADCONFIG_H
+
+#define JTHREADCONFIG_H
+
+#define JTHREAD_IMPORT ${JTHREAD_IMPORT}
+#define JTHREAD_EXPORT ${JTHREAD_EXPORT}
+#ifdef JTHREAD_COMPILING
+	#define JTHREAD_IMPORTEXPORT JTHREAD_EXPORT
+#else
+	#define JTHREAD_IMPORTEXPORT JTHREAD_IMPORT
+#endif // JTHREAD_COMPILING
+
+${JTHREAD_CONFIG_WIN32THREADS}
+
+${JTHREAD_CONFIG_JMUTEXCRITICALSECTION}
+
+#endif // JTHREADCONFIG_H
+

+ 93 - 0
lib/common/jrtplib/src/rtcpapppacket.cpp

@@ -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
+

+ 132 - 0
lib/common/jrtplib/src/rtcpapppacket.h

@@ -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
+

+ 104 - 0
lib/common/jrtplib/src/rtcpbyepacket.cpp

@@ -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
+

+ 140 - 0
lib/common/jrtplib/src/rtcpbyepacket.h

@@ -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
+

+ 232 - 0
lib/common/jrtplib/src/rtcpcompoundpacket.cpp

@@ -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
+

+ 111 - 0
lib/common/jrtplib/src/rtcpcompoundpacket.h

@@ -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. */
+	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;
+
+	uint8_t *compoundpacket;
+	size_t compoundpacketlength;
+	bool deletepacket;
+	
+	std::list<RTCPPacket *> rtcppacklist;
+	std::list<RTCPPacket *>::const_iterator rtcppackit;
+};
+
+} // end namespace
+
+#endif // RTCPCOMPOUNDPACKET_H
+

+ 815 - 0
lib/common/jrtplib/src/rtcpcompoundpacketbuilder.cpp

@@ -0,0 +1,815 @@
+/*
+
+  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"
+//
+//include "rtpmemorymanager.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
+

+ 400 - 0
lib/common/jrtplib/src/rtcpcompoundpacketbuilder.h

@@ -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
+

+ 76 - 0
lib/common/jrtplib/src/rtcppacket.cpp

@@ -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

+ 94 - 0
lib/common/jrtplib/src/rtcppacket.h

@@ -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
+

+ 741 - 0
lib/common/jrtplib/src/rtcppacketbuilder.cpp

@@ -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
+

+ 229 - 0
lib/common/jrtplib/src/rtcppacketbuilder.h

@@ -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
+

+ 100 - 0
lib/common/jrtplib/src/rtcprrpacket.cpp

@@ -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
+

+ 206 - 0
lib/common/jrtplib/src/rtcprrpacket.h

@@ -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
+

+ 423 - 0
lib/common/jrtplib/src/rtcpscheduler.cpp

@@ -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
+

+ 189 - 0
lib/common/jrtplib/src/rtcpscheduler.h

@@ -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
+

+ 182 - 0
lib/common/jrtplib/src/rtcpsdesinfo.cpp

@@ -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
+

+ 220 - 0
lib/common/jrtplib/src/rtcpsdesinfo.h

@@ -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
+

+ 236 - 0
lib/common/jrtplib/src/rtcpsdespacket.cpp

@@ -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
+

+ 386 - 0
lib/common/jrtplib/src/rtcpsdespacket.h

@@ -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
+

+ 106 - 0
lib/common/jrtplib/src/rtcpsrpacket.cpp

@@ -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
+

+ 252 - 0
lib/common/jrtplib/src/rtcpsrpacket.h

@@ -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
+

+ 73 - 0
lib/common/jrtplib/src/rtcpunknownpacket.h

@@ -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
+

+ 99 - 0
lib/common/jrtplib/src/rtpaddress.h

@@ -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
+

+ 105 - 0
lib/common/jrtplib/src/rtpbyteaddress.cpp

@@ -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

+ 93 - 0
lib/common/jrtplib/src/rtpbyteaddress.h

@@ -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
+

+ 130 - 0
lib/common/jrtplib/src/rtpcollisionlist.cpp

@@ -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
+

+ 95 - 0
lib/common/jrtplib/src/rtpcollisionlist.h

@@ -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
+

+ 78 - 0
lib/common/jrtplib/src/rtpconfig.h

@@ -0,0 +1,78 @@
+/*
+
+  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 
+#ifdef JRTPLIB_COMPILING
+	#define JRTPLIB_IMPORTEXPORT JRTPLIB_EXPORT
+#else
+	#define JRTPLIB_IMPORTEXPORT JRTPLIB_IMPORT
+#endif // JRTPLIB_COMPILING
+
+// Don't have <sys/filio.h>
+
+// Don't have <sys/sockio.h>
+
+// Little endian system
+
+#define RTP_SOCKLENTYPE_UINT
+
+// No sa_len member in struct sockaddr
+
+#define RTP_SUPPORT_IPV4MULTICAST
+
+#define RTP_SUPPORT_THREAD
+
+#define RTP_SUPPORT_SDESPRIV
+
+#define RTP_SUPPORT_PROBATION
+
+// Not using getlogin_r
+
+#define RTP_SUPPORT_IPV6
+
+// No IPv6 multicasting support
+
+// No ifaddrs support
+
+#define RTP_SUPPORT_SENDAPP
+
+#define RTP_SUPPORT_MEMORYMANAGEMENT
+
+// No support for sending unknown RTCP packets
+
+#endif // RTPCONFIG_UNIX_H
+

+ 78 - 0
lib/common/jrtplib/src/rtpconfig.h.in

@@ -0,0 +1,78 @@
+/*
+
+  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 ${JRTPLIB_IMPORT}
+#define JRTPLIB_EXPORT ${JRTPLIB_EXPORT}
+#ifdef JRTPLIB_COMPILING
+	#define JRTPLIB_IMPORTEXPORT JRTPLIB_EXPORT
+#else
+	#define JRTPLIB_IMPORTEXPORT JRTPLIB_IMPORT
+#endif // JRTPLIB_COMPILING
+
+${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}
+
+${RTP_SUPPORT_IPV6}
+
+${RTP_SUPPORT_IPV6MULTICAST}
+
+${RTP_SUPPORT_IFADDRS}
+
+${RTP_SUPPORT_SENDAPP}
+
+${RTP_SUPPORT_MEMORYMANAGEMENT}
+
+${RTP_SUPPORT_RTCPUNKNOWN}
+
+#endif // RTPCONFIG_UNIX_H
+

+ 178 - 0
lib/common/jrtplib/src/rtpdebug.cpp

@@ -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
+

+ 52 - 0
lib/common/jrtplib/src/rtpdebug.h

@@ -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
+

+ 86 - 0
lib/common/jrtplib/src/rtpdefines.h

@@ -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
+

+ 257 - 0
lib/common/jrtplib/src/rtperrors.cpp

@@ -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
+

+ 236 - 0
lib/common/jrtplib/src/rtperrors.h

@@ -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
+

+ 925 - 0
lib/common/jrtplib/src/rtpexternaltransmitter.cpp

@@ -0,0 +1,925 @@
+/*
+
+  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()
+{
+	if (pipe(abortdesc) < 0)
+		return ERR_RTP_EXTERNALTRANS_CANTCREATEPIPE;
+	return 0;
+}
+
+void RTPExternalTransmitter::DestroyAbortDescriptors()
+{
+	close(abortdesc[0]);
+	close(abortdesc[1]);
+}
+
+#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
+

+ 241 - 0
lib/common/jrtplib/src/rtpexternaltransmitter.h

@@ -0,0 +1,241 @@
+/*
+
+  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.h"
+    #include "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
+
+

+ 342 - 0
lib/common/jrtplib/src/rtphashtable.h

@@ -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
+

+ 287 - 0
lib/common/jrtplib/src/rtpinternalsourcedata.cpp

@@ -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
+

+ 135 - 0
lib/common/jrtplib/src/rtpinternalsourcedata.h

@@ -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
+

+ 89 - 0
lib/common/jrtplib/src/rtpipv4address.cpp

@@ -0,0 +1,89 @@
+/*
+
+  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
+{
+
+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
+

+ 95 - 0
lib/common/jrtplib/src/rtpipv4address.h

@@ -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):RTPAddress(IPv4Address)						{ RTPIPv4Address::ip = ip; RTPIPv4Address::port = port; }
+	
+	/** 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):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()																				{ }
+
+	/** 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
+

+ 113 - 0
lib/common/jrtplib/src/rtpipv4destination.h

@@ -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
+

+ 113 - 0
lib/common/jrtplib/src/rtpipv6address.cpp

@@ -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
+

+ 110 - 0
lib/common/jrtplib/src/rtpipv6address.h

@@ -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
+

+ 114 - 0
lib/common/jrtplib/src/rtpipv6destination.h

@@ -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
+

+ 344 - 0
lib/common/jrtplib/src/rtpkeyhashtable.h

@@ -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

+ 55 - 0
lib/common/jrtplib/src/rtplibraryversion.cpp

@@ -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
+

+ 77 - 0
lib/common/jrtplib/src/rtplibraryversion.h

@@ -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
+

+ 257 - 0
lib/common/jrtplib/src/rtpmemorymanager.h

@@ -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
+

+ 74 - 0
lib/common/jrtplib/src/rtpmemoryobject.h

@@ -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
+

+ 350 - 0
lib/common/jrtplib/src/rtppacket.cpp

@@ -0,0 +1,350 @@
+/*
+
+  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);
+}
+
+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
+

+ 183 - 0
lib/common/jrtplib/src/rtppacket.h

@@ -0,0 +1,183 @@
+/*
+
+  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 (packet && !externalbuffer) RTPDeleteByteArray(packet,GetMemoryManager());  }
+
+	/** 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; }
+	
+	/** 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
+

+ 274 - 0
lib/common/jrtplib/src/rtppacketbuilder.cpp

@@ -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();
+
+	// 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();
+
+	// 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
+

+ 274 - 0
lib/common/jrtplib/src/rtppacketbuilder.h

@@ -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
+

+ 180 - 0
lib/common/jrtplib/src/rtppollthread.cpp

@@ -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
+

+ 79 - 0
lib/common/jrtplib/src/rtppollthread.h

@@ -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.h"
+#include "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

+ 86 - 0
lib/common/jrtplib/src/rtprandom.cpp

@@ -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
+

+ 76 - 0
lib/common/jrtplib/src/rtprandom.h

@@ -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
+

+ 125 - 0
lib/common/jrtplib/src/rtprandomrand48.cpp

@@ -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
+

+ 76 - 0
lib/common/jrtplib/src/rtprandomrand48.h

@@ -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 rtprandomrand48.h
+ */
+
+#ifndef RTPRANDOMRAND48_H
+
+#define RTPRANDOMRAND48_H
+
+#include "rtpconfig.h"
+#include "rtprandom.h"
+#ifdef RTP_SUPPORT_THREAD
+#include "jthread.h"
+#include "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
+

+ 200 - 0
lib/common/jrtplib/src/rtprandomrands.cpp

@@ -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
+

+ 70 - 0
lib/common/jrtplib/src/rtprandomrands.h

@@ -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
+

+ 123 - 0
lib/common/jrtplib/src/rtprandomurandom.cpp

@@ -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
+

+ 68 - 0
lib/common/jrtplib/src/rtprandomurandom.h

@@ -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

+ 114 - 0
lib/common/jrtplib/src/rtprawpacket.h

@@ -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
+

+ 1659 - 0
lib/common/jrtplib/src/rtpsession.cpp

@@ -0,0 +1,1659 @@
+/*
+
+  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 "rtpsession.h"
+#include "rtperrors.h"
+#include "rtppollthread.h"
+#include "rtpudpv4transmitter.h"
+#include "rtpudpv6transmitter.h"
+#include "rtpexternaltransmitter.h"
+#include "rtpsessionparams.h"
+#include "rtpdefines.h"
+#include "rtprawpacket.h"
+#include "rtppacket.h"
+#include "rtptimeutilities.h"
+#include "rtpmemorymanager.h"
+#include "rtprandomrand48.h"
+#include "rtprandomrands.h"
+#include "rtprandomurandom.h"
+#ifdef RTP_SUPPORT_SENDAPP
+	#include "rtcpcompoundpacket.h"
+#endif // RTP_SUPPORT_SENDAPP
+#ifndef WIN32
+	#include <unistd.h>
+	#include <stdlib.h>
+#else
+	#include <winbase.h>
+#endif // WIN32
+
+#ifdef RTPDEBUG
+	#include <iostream>
+#endif // RTPDEBUG
+
+#include "rtpdebug.h"
+
+#ifdef RTP_SUPPORT_THREAD
+	#define SOURCES_LOCK					{ if (usingpollthread) sourcesmutex.Lock(); }
+	#define SOURCES_UNLOCK					{ if (usingpollthread) sourcesmutex.Unlock(); }
+	#define BUILDER_LOCK					{ if (usingpollthread) buildermutex.Lock(); }
+	#define BUILDER_UNLOCK					{ if (usingpollthread) buildermutex.Unlock(); }
+	#define SCHED_LOCK					{ if (usingpollthread) schedmutex.Lock(); }
+	#define SCHED_UNLOCK					{ if (usingpollthread) schedmutex.Unlock(); }
+	#define PACKSENT_LOCK					{ if (usingpollthread) packsentmutex.Lock(); }
+	#define PACKSENT_UNLOCK					{ if (usingpollthread) packsentmutex.Unlock(); } 
+#else
+	#define SOURCES_LOCK
+	#define SOURCES_UNLOCK
+	#define BUILDER_LOCK
+	#define BUILDER_UNLOCK
+	#define SCHED_LOCK
+	#define SCHED_UNLOCK
+	#define PACKSENT_LOCK
+	#define PACKSENT_UNLOCK
+#endif // RTP_SUPPORT_THREAD
+
+namespace jrtplib
+{
+
+RTPSession::RTPSession(RTPRandom *r,RTPMemoryManager *mgr) 
+	: RTPMemoryObject(mgr),sources(*this,mgr),rtprnd(GetRandomNumberGenerator(r)),packetbuilder(*rtprnd,mgr),rtcpsched(sources,*rtprnd),
+	  rtcpbuilder(sources,packetbuilder,mgr),collisionlist(mgr)
+{
+	created = false;
+#if (defined(WIN32) || defined(_WIN32_WCE))
+	timeinit.Dummy();
+#endif // WIN32 || _WIN32_WCE
+
+	//std::cout << (void *)(rtprnd) << std::endl;
+}
+
+RTPSession::~RTPSession()
+{
+	Destroy();
+
+	if (deletertprnd)
+		delete rtprnd;
+}
+
+int RTPSession::Create(const RTPSessionParams &sessparams,const RTPTransmissionParams *transparams /* = 0 */,
+		       RTPTransmitter::TransmissionProtocol protocol)
+{
+	int status;
+	
+	if (created)
+		return ERR_RTP_SESSION_ALREADYCREATED;
+
+	usingpollthread = sessparams.IsUsingPollThread();
+	useSR_BYEifpossible = sessparams.GetSenderReportForBYE();
+	sentpackets = false;
+	
+	// Check max packet size
+	
+	if ((maxpacksize = sessparams.GetMaximumPacketSize()) < RTP_MINPACKETSIZE)
+		return ERR_RTP_SESSION_MAXPACKETSIZETOOSMALL;
+		
+	// Initialize the transmission component
+	
+	rtptrans = 0;
+	switch(protocol)
+	{
+	case RTPTransmitter::IPv4UDPProto:
+		rtptrans = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPTRANSMITTER) RTPUDPv4Transmitter(GetMemoryManager());
+		break;
+#ifdef RTP_SUPPORT_IPV6
+	case RTPTransmitter::IPv6UDPProto:
+		rtptrans = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPTRANSMITTER) RTPUDPv6Transmitter(GetMemoryManager());
+		break;
+#endif // RTP_SUPPORT_IPV6
+	case RTPTransmitter::ExternalProto:
+		rtptrans = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPTRANSMITTER) RTPExternalTransmitter(GetMemoryManager());
+		break;
+	case RTPTransmitter::UserDefinedProto:
+		rtptrans = NewUserDefinedTransmitter();
+		if (rtptrans == 0)
+			return ERR_RTP_SESSION_USERDEFINEDTRANSMITTERNULL;
+		break;
+	default:
+		return ERR_RTP_SESSION_UNSUPPORTEDTRANSMISSIONPROTOCOL;
+	}
+	
+	if (rtptrans == 0)
+		return ERR_RTP_OUTOFMEM;
+	if ((status = rtptrans->Init(usingpollthread)) < 0)
+	{
+		RTPDelete(rtptrans,GetMemoryManager());
+		return status;
+	}
+	if ((status = rtptrans->Create(maxpacksize,transparams)) < 0)
+	{
+		RTPDelete(rtptrans,GetMemoryManager());
+		return status;
+	}
+
+	deletetransmitter = true;
+	return InternalCreate(sessparams);
+}
+
+int RTPSession::Create(const RTPSessionParams &sessparams,RTPTransmitter *transmitter)
+{
+	int status;
+	
+	if (created)
+		return ERR_RTP_SESSION_ALREADYCREATED;
+
+	usingpollthread = sessparams.IsUsingPollThread();
+	useSR_BYEifpossible = sessparams.GetSenderReportForBYE();
+	sentpackets = false;
+	
+	// Check max packet size
+	
+	if ((maxpacksize = sessparams.GetMaximumPacketSize()) < RTP_MINPACKETSIZE)
+		return ERR_RTP_SESSION_MAXPACKETSIZETOOSMALL;
+		
+	rtptrans = transmitter;
+
+	if ((status = rtptrans->SetMaximumPacketSize(maxpacksize)) < 0)
+		return status;
+
+	deletetransmitter = false;
+	return InternalCreate(sessparams);
+}
+
+int RTPSession::InternalCreate(const RTPSessionParams &sessparams)
+{
+	int status;
+
+	// Initialize packet builder
+	
+	if ((status = packetbuilder.Init(maxpacksize)) < 0)
+	{
+		if (deletetransmitter)
+			RTPDelete(rtptrans,GetMemoryManager());
+		return status;
+	}
+
+	if (sessparams.GetUsePredefinedSSRC())
+		packetbuilder.AdjustSSRC(sessparams.GetPredefinedSSRC());
+
+#ifdef RTP_SUPPORT_PROBATION
+
+	// Set probation type
+	sources.SetProbationType(sessparams.GetProbationType());
+
+#endif // RTP_SUPPORT_PROBATION
+
+	// Add our own ssrc to the source table
+	
+	if ((status = sources.CreateOwnSSRC(packetbuilder.GetSSRC())) < 0)
+	{
+		packetbuilder.Destroy();
+		if (deletetransmitter)
+			RTPDelete(rtptrans,GetMemoryManager());
+		return status;
+	}
+
+	// Set the initial receive mode
+	
+	if ((status = rtptrans->SetReceiveMode(sessparams.GetReceiveMode())) < 0)
+	{
+		packetbuilder.Destroy();
+		sources.Clear();
+		if (deletetransmitter)
+			RTPDelete(rtptrans,GetMemoryManager());
+		return status;
+	}
+
+	// Init the RTCP packet builder
+	
+	double timestampunit = sessparams.GetOwnTimestampUnit();
+	uint8_t buf[1024];
+	size_t buflen = 1024;
+	std::string forcedcname = sessparams.GetCNAME(); 
+
+	if (forcedcname.length() == 0)
+	{
+		if ((status = CreateCNAME(buf,&buflen,sessparams.GetResolveLocalHostname())) < 0)
+		{
+			packetbuilder.Destroy();
+			sources.Clear();
+			if (deletetransmitter)
+				RTPDelete(rtptrans,GetMemoryManager());
+			return status;
+		}
+	}
+	else
+	{
+		strncpy((char *)buf, forcedcname.c_str(), buflen);
+		buf[buflen-1] = 0;
+		buflen = strlen((char *)buf);
+	}
+	
+	if ((status = rtcpbuilder.Init(maxpacksize,timestampunit,buf,buflen)) < 0)
+	{
+		packetbuilder.Destroy();
+		sources.Clear();
+		if (deletetransmitter)
+			RTPDelete(rtptrans,GetMemoryManager());
+		return status;
+	}
+
+	// Set scheduler parameters
+	
+	rtcpsched.Reset();
+	rtcpsched.SetHeaderOverhead(rtptrans->GetHeaderOverhead());
+
+	RTCPSchedulerParams schedparams;
+
+	sessionbandwidth = sessparams.GetSessionBandwidth();
+	controlfragment = sessparams.GetControlTrafficFraction();
+	
+	if ((status = schedparams.SetRTCPBandwidth(sessionbandwidth*controlfragment)) < 0)
+	{
+		if (deletetransmitter)
+			RTPDelete(rtptrans,GetMemoryManager());
+		packetbuilder.Destroy();
+		sources.Clear();
+		rtcpbuilder.Destroy();
+		return status;
+	}
+	if ((status = schedparams.SetSenderBandwidthFraction(sessparams.GetSenderControlBandwidthFraction())) < 0)
+	{
+		if (deletetransmitter)
+			RTPDelete(rtptrans,GetMemoryManager());
+		packetbuilder.Destroy();
+		sources.Clear();
+		rtcpbuilder.Destroy();
+		return status;
+	}
+	if ((status = schedparams.SetMinimumTransmissionInterval(sessparams.GetMinimumRTCPTransmissionInterval())) < 0)
+	{
+		if (deletetransmitter)
+			RTPDelete(rtptrans,GetMemoryManager());
+		packetbuilder.Destroy();
+		sources.Clear();
+		rtcpbuilder.Destroy();
+		return status;
+	}
+	schedparams.SetUseHalfAtStartup(sessparams.GetUseHalfRTCPIntervalAtStartup());
+	schedparams.SetRequestImmediateBYE(sessparams.GetRequestImmediateBYE());
+	
+	rtcpsched.SetParameters(schedparams);
+
+	// copy other parameters
+	
+	acceptownpackets = sessparams.AcceptOwnPackets();
+	membermultiplier = sessparams.GetSourceTimeoutMultiplier();
+	sendermultiplier = sessparams.GetSenderTimeoutMultiplier();
+	byemultiplier = sessparams.GetBYETimeoutMultiplier();
+	collisionmultiplier = sessparams.GetCollisionTimeoutMultiplier();
+	notemultiplier = sessparams.GetNoteTimeoutMultiplier();
+
+	// Do thread stuff if necessary
+	
+#ifdef RTP_SUPPORT_THREAD
+	pollthread = 0;
+	if (usingpollthread)
+	{
+		if (!sourcesmutex.IsInitialized())	
+		{
+			if (sourcesmutex.Init() < 0)
+			{
+				if (deletetransmitter)
+					RTPDelete(rtptrans,GetMemoryManager());
+				packetbuilder.Destroy();
+				sources.Clear();
+				rtcpbuilder.Destroy();
+				return ERR_RTP_SESSION_CANTINITMUTEX;
+			}
+		}
+		if (!buildermutex.IsInitialized())
+		{
+			if (buildermutex.Init() < 0)
+			{
+				if (deletetransmitter)
+					RTPDelete(rtptrans,GetMemoryManager());
+				packetbuilder.Destroy();
+				sources.Clear();
+				rtcpbuilder.Destroy();
+				return ERR_RTP_SESSION_CANTINITMUTEX;
+			}
+		}
+		if (!schedmutex.IsInitialized())
+		{
+			if (schedmutex.Init() < 0)
+			{
+				if (deletetransmitter)
+					RTPDelete(rtptrans,GetMemoryManager());
+				packetbuilder.Destroy();
+				sources.Clear();
+				rtcpbuilder.Destroy();
+				return ERR_RTP_SESSION_CANTINITMUTEX;
+			}
+		}
+		if (!packsentmutex.IsInitialized())
+		{
+			if (packsentmutex.Init() < 0)
+			{
+				if (deletetransmitter)
+					RTPDelete(rtptrans,GetMemoryManager());
+				packetbuilder.Destroy();
+				sources.Clear();
+				rtcpbuilder.Destroy();
+				return ERR_RTP_SESSION_CANTINITMUTEX;
+			}
+		}
+		
+		pollthread = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPPOLLTHREAD) RTPPollThread(*this,rtcpsched);
+		if (pollthread == 0)
+		{
+			if (deletetransmitter)
+				RTPDelete(rtptrans,GetMemoryManager());
+			packetbuilder.Destroy();
+			sources.Clear();
+			rtcpbuilder.Destroy();
+			return ERR_RTP_OUTOFMEM;
+		}
+		if ((status = pollthread->Start(rtptrans)) < 0)
+		{
+			if (deletetransmitter)
+				RTPDelete(rtptrans,GetMemoryManager());
+			RTPDelete(pollthread,GetMemoryManager());
+			packetbuilder.Destroy();
+			sources.Clear();
+			rtcpbuilder.Destroy();
+			return status;
+		}
+	}
+#endif // RTP_SUPPORT_THREAD	
+	
+	created = true;
+	return 0;
+}
+
+
+void RTPSession::Destroy()
+{
+	if (!created)
+		return;
+
+#ifdef RTP_SUPPORT_THREAD
+	if (pollthread)
+		RTPDelete(pollthread,GetMemoryManager());
+#endif // RTP_SUPPORT_THREAD
+	
+	if (deletetransmitter)
+		RTPDelete(rtptrans,GetMemoryManager());
+	packetbuilder.Destroy();
+	rtcpbuilder.Destroy();
+	rtcpsched.Reset();
+	collisionlist.Clear();
+	sources.Clear();
+
+	std::list<RTCPCompoundPacket *>::const_iterator it;
+
+	for (it = byepackets.begin() ; it != byepackets.end() ; it++)
+		RTPDelete(*it,GetMemoryManager());
+	byepackets.clear();
+	
+	created = false;
+}
+
+void RTPSession::BYEDestroy(const RTPTime &maxwaittime,const void *reason,size_t reasonlength)
+{
+	if (!created)
+		return;
+
+	// first, stop the thread so we have full control over all components
+	
+#ifdef RTP_SUPPORT_THREAD
+	if (pollthread)
+		RTPDelete(pollthread,GetMemoryManager());
+#endif // RTP_SUPPORT_THREAD
+
+	RTPTime stoptime = RTPTime::CurrentTime();
+	stoptime += maxwaittime;
+
+	// add bye packet to the list if we've sent data
+
+	RTCPCompoundPacket *pack;
+
+	if (sentpackets)
+	{
+		int status;
+		
+		reasonlength = (reasonlength>RTCP_BYE_MAXREASONLENGTH)?RTCP_BYE_MAXREASONLENGTH:reasonlength;
+	       	status = rtcpbuilder.BuildBYEPacket(&pack,reason,reasonlength,useSR_BYEifpossible);
+		if (status >= 0)
+		{
+			byepackets.push_back(pack);
+	
+			if (byepackets.size() == 1)
+				rtcpsched.ScheduleBYEPacket(pack->GetCompoundPacketLength());
+		}
+	}
+	
+	if (!byepackets.empty())
+	{
+		bool done = false;
+		
+		while (!done)
+		{
+			RTPTime curtime = RTPTime::CurrentTime();
+			
+			if (curtime >= stoptime)
+				done = true;
+		
+			if (rtcpsched.IsTime())
+			{
+				pack = *(byepackets.begin());
+				byepackets.pop_front();
+			
+				rtptrans->SendRTCPData(pack->GetCompoundPacketData(),pack->GetCompoundPacketLength());
+				
+				OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering
+				
+				RTPDelete(pack,GetMemoryManager());
+				if (!byepackets.empty()) // more bye packets to send, schedule them
+					rtcpsched.ScheduleBYEPacket((*(byepackets.begin()))->GetCompoundPacketLength());
+				else
+					done = true;
+			}
+			if (!done)
+				RTPTime::Wait(RTPTime(0,100000));
+		}
+	}
+	
+	if (deletetransmitter)
+		RTPDelete(rtptrans,GetMemoryManager());
+	packetbuilder.Destroy();
+	rtcpbuilder.Destroy();
+	rtcpsched.Reset();
+	collisionlist.Clear();
+	sources.Clear();
+
+	// clear rest of bye packets
+	std::list<RTCPCompoundPacket *>::const_iterator it;
+
+	for (it = byepackets.begin() ; it != byepackets.end() ; it++)
+		RTPDelete(*it,GetMemoryManager());
+	byepackets.clear();
+	
+	created = false;
+}
+
+bool RTPSession::IsActive()
+{
+	return created;
+}
+
+uint32_t RTPSession::GetLocalSSRC()
+{
+	if (!created)
+		return 0;
+	
+	uint32_t ssrc;
+
+	BUILDER_LOCK
+	ssrc = packetbuilder.GetSSRC();
+	BUILDER_UNLOCK
+	return ssrc;
+}
+
+int RTPSession::AddDestination(const RTPAddress &addr)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	return rtptrans->AddDestination(addr);
+}
+
+int RTPSession::DeleteDestination(const RTPAddress &addr)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	return rtptrans->DeleteDestination(addr);
+}
+
+void RTPSession::ClearDestinations()
+{
+	if (!created)
+		return;
+	rtptrans->ClearDestinations();
+}
+
+bool RTPSession::SupportsMulticasting()
+{
+	if (!created)
+		return false;
+	return rtptrans->SupportsMulticasting();
+}
+
+int RTPSession::JoinMulticastGroup(const RTPAddress &addr)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	return rtptrans->JoinMulticastGroup(addr);
+}
+
+int RTPSession::LeaveMulticastGroup(const RTPAddress &addr)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	return rtptrans->LeaveMulticastGroup(addr);
+}
+
+void RTPSession::LeaveAllMulticastGroups()
+{
+	if (!created)
+		return;
+	rtptrans->LeaveAllMulticastGroups();
+}
+
+int RTPSession::SendPacket(const void *data,size_t len)
+{
+	int status;
+	
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	BUILDER_LOCK
+	if ((status = packetbuilder.BuildPacket(data,len)) < 0)
+	{
+		BUILDER_UNLOCK
+		return status;
+	}
+	if ((status = rtptrans->SendRTPData(packetbuilder.GetPacket(),packetbuilder.GetPacketLength())) < 0)
+	{
+		BUILDER_UNLOCK
+		return status;
+	}
+	BUILDER_UNLOCK
+
+	SOURCES_LOCK
+	sources.SentRTPPacket();
+	SOURCES_UNLOCK
+	PACKSENT_LOCK
+	sentpackets = true;
+	PACKSENT_UNLOCK
+	return 0;
+}
+
+int RTPSession::SendPacket(const void *data,size_t len,
+                uint8_t pt,bool mark,uint32_t timestampinc)
+{
+	int status;
+
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	
+	BUILDER_LOCK
+	if ((status = packetbuilder.BuildPacket(data,len,pt,mark,timestampinc)) < 0)
+	{
+		BUILDER_UNLOCK
+		return status;
+	}
+
+	if ((status = rtptrans->SendRTPData(packetbuilder.GetPacket(),packetbuilder.GetPacketLength())) < 0)
+	{
+		BUILDER_UNLOCK
+		return status;
+	}
+	BUILDER_UNLOCK
+	
+	SOURCES_LOCK
+	sources.SentRTPPacket();
+	SOURCES_UNLOCK
+	PACKSENT_LOCK
+	sentpackets = true;
+	PACKSENT_UNLOCK
+	return 0;
+}
+
+int RTPSession::SendPacketEx(const void *data,size_t len,
+                  uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords)
+{
+	int status;
+	
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	BUILDER_LOCK
+	if ((status = packetbuilder.BuildPacketEx(data,len,hdrextID,hdrextdata,numhdrextwords)) < 0)
+	{
+		BUILDER_UNLOCK
+		return status;
+	}
+	if ((status = rtptrans->SendRTPData(packetbuilder.GetPacket(),packetbuilder.GetPacketLength())) < 0)
+	{
+		BUILDER_UNLOCK
+		return status;
+	}
+	BUILDER_UNLOCK
+
+	SOURCES_LOCK
+	sources.SentRTPPacket();
+	SOURCES_UNLOCK
+	PACKSENT_LOCK
+	sentpackets = true;
+	PACKSENT_UNLOCK
+	return 0;
+}
+
+int RTPSession::SendPacketEx(const void *data,size_t len,
+                  uint8_t pt,bool mark,uint32_t timestampinc,
+                  uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords)
+{
+	int status;
+	
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	
+	BUILDER_LOCK
+	if ((status = packetbuilder.BuildPacketEx(data,len,pt,mark,timestampinc,hdrextID,hdrextdata,numhdrextwords)) < 0)
+	{
+		BUILDER_UNLOCK
+		return status;
+	}
+	if ((status = rtptrans->SendRTPData(packetbuilder.GetPacket(),packetbuilder.GetPacketLength())) < 0)
+	{
+		BUILDER_UNLOCK
+		return status;
+	}
+	BUILDER_UNLOCK
+
+	SOURCES_LOCK
+	sources.SentRTPPacket();
+	SOURCES_UNLOCK
+	PACKSENT_LOCK
+	sentpackets = true;
+	PACKSENT_UNLOCK
+	return 0;
+}
+
+#ifdef RTP_SUPPORT_SENDAPP
+
+int RTPSession::SendRTCPAPPPacket(uint8_t subtype, const uint8_t name[4], const void *appdata, size_t appdatalen)
+{
+	int status;
+
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	BUILDER_LOCK
+	uint32_t ssrc = packetbuilder.GetSSRC();
+	BUILDER_UNLOCK
+	
+	RTCPCompoundPacketBuilder pb(GetMemoryManager());
+
+	status = pb.InitBuild(maxpacksize);
+	
+	if(status < 0)
+		return status;
+
+	//first packet in an rtcp compound packet should always be SR or RR
+	if((status = pb.StartReceiverReport(ssrc)) < 0)
+		return status;
+
+	//add SDES packet with CNAME item
+	if ((status = pb.AddSDESSource(ssrc)) < 0)
+		return status;
+	
+	BUILDER_LOCK
+	size_t owncnamelen = 0;
+	uint8_t *owncname = rtcpbuilder.GetLocalCNAME(&owncnamelen);
+
+	if ((status = pb.AddSDESNormalItem(RTCPSDESPacket::CNAME,owncname,owncnamelen)) < 0)
+	{
+		BUILDER_UNLOCK
+		return status;
+	}
+	BUILDER_UNLOCK
+	
+	//add our application specific packet
+	if((status = pb.AddAPPPacket(subtype, ssrc, name, appdata, appdatalen)) < 0)
+		return status;
+
+	if((status = pb.EndBuild()) < 0)
+		return status;
+
+	//send packet
+	status = rtptrans->SendRTCPData(pb.GetCompoundPacketData(),pb.GetCompoundPacketLength());
+	if(status < 0)
+		return status;
+
+	PACKSENT_LOCK
+	sentpackets = true;
+	PACKSENT_UNLOCK
+
+	return pb.GetCompoundPacketLength();
+}
+
+#endif // RTP_SUPPORT_SENDAPP
+
+#ifdef RTP_SUPPORT_RTCPUNKNOWN
+
+int RTPSession::SendUnknownPacket(bool sr, uint8_t payload_type, uint8_t subtype, const void *data, size_t len)
+{
+	int status;
+
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	BUILDER_LOCK
+	uint32_t ssrc = packetbuilder.GetSSRC();
+	BUILDER_UNLOCK
+	
+	RTCPCompoundPacketBuilder* rtcpcomppack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPCOMPOUNDPACKETBUILDER) RTCPCompoundPacketBuilder(GetMemoryManager());
+	if (rtcpcomppack == 0)
+	{
+		RTPDelete(rtcpcomppack,GetMemoryManager());
+		return ERR_RTP_OUTOFMEM;
+	}
+
+	status = rtcpcomppack->InitBuild(maxpacksize);	
+	if(status < 0)
+	{
+		RTPDelete(rtcpcomppack,GetMemoryManager());
+		return status;
+	}
+
+	if (sr)
+	{
+		// setup for the rtcp 
+		RTPTime rtppacktime = packetbuilder.GetPacketTime();
+		uint32_t rtppacktimestamp = packetbuilder.GetPacketTimestamp();
+		uint32_t packcount = packetbuilder.GetPacketCount();
+		uint32_t octetcount = packetbuilder.GetPayloadOctetCount();
+		RTPTime curtime = RTPTime::CurrentTime();
+		RTPTime diff = curtime;
+		diff -= rtppacktime;
+		diff += 1; // add transmission delay or RTPTime(0,0);
+
+		double timestampunit = 90000;
+
+		uint32_t tsdiff = (uint32_t)((diff.GetDouble()/timestampunit)+0.5);
+		uint32_t rtptimestamp = rtppacktimestamp+tsdiff;
+		RTPNTPTime ntptimestamp = curtime.GetNTPTime();
+
+		//first packet in an rtcp compound packet should always be SR or RR
+		if((status = rtcpcomppack->StartSenderReport(ssrc,ntptimestamp,rtptimestamp,packcount,octetcount)) < 0)
+		{
+			RTPDelete(rtcpcomppack,GetMemoryManager());
+			return status;
+		}
+	}
+	else
+	{
+		//first packet in an rtcp compound packet should always be SR or RR
+		if((status = rtcpcomppack->StartReceiverReport(ssrc)) < 0)
+		{
+			RTPDelete(rtcpcomppack,GetMemoryManager());
+			return status;
+		}
+
+	}
+
+	//add SDES packet with CNAME item
+	if ((status = rtcpcomppack->AddSDESSource(ssrc)) < 0)
+	{
+		RTPDelete(rtcpcomppack,GetMemoryManager());
+		return status;
+	}
+	
+	BUILDER_LOCK
+	size_t owncnamelen = 0;
+	uint8_t *owncname = rtcpbuilder.GetLocalCNAME(&owncnamelen);
+
+	if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::CNAME,owncname,owncnamelen)) < 0)
+	{
+		BUILDER_UNLOCK
+		RTPDelete(rtcpcomppack,GetMemoryManager());
+		return status;
+	}
+	BUILDER_UNLOCK
+	
+	//add our packet
+	if((status = rtcpcomppack->AddUnknownPacket(payload_type, subtype, ssrc, data, len)) < 0)
+	{
+		RTPDelete(rtcpcomppack,GetMemoryManager());
+		return status;
+	}
+
+	if((status = rtcpcomppack->EndBuild()) < 0)
+	{
+		RTPDelete(rtcpcomppack,GetMemoryManager());
+		return status;
+	}
+
+	//send packet
+	status = rtptrans->SendRTCPData(rtcpcomppack->GetCompoundPacketData(),
+		rtcpcomppack->GetCompoundPacketLength());
+	if(status < 0)
+	{
+		RTPDelete(rtcpcomppack,GetMemoryManager());
+		return status;
+	}
+
+	PACKSENT_LOCK
+	sentpackets = true;
+	PACKSENT_UNLOCK
+
+	OnSendRTCPCompoundPacket(rtcpcomppack); // we'll place this after the actual send to avoid tampering
+
+	int retlen = rtcpcomppack->GetCompoundPacketLength();
+
+	RTPDelete(rtcpcomppack,GetMemoryManager());
+	return retlen;
+}
+
+#endif // RTP_SUPPORT_RTCPUNKNOWN 
+
+int RTPSession::SetDefaultPayloadType(uint8_t pt)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	
+	int status;
+	
+	BUILDER_LOCK
+	status = packetbuilder.SetDefaultPayloadType(pt);
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::SetDefaultMark(bool m)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+
+	BUILDER_LOCK
+	status = packetbuilder.SetDefaultMark(m);
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::SetDefaultTimestampIncrement(uint32_t timestampinc)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+
+	BUILDER_LOCK
+	status = packetbuilder.SetDefaultTimestampIncrement(timestampinc);
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::IncrementTimestamp(uint32_t inc)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+
+	BUILDER_LOCK
+	status = packetbuilder.IncrementTimestamp(inc);
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::IncrementTimestampDefault()
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+	
+	BUILDER_LOCK
+	status = packetbuilder.IncrementTimestampDefault();
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::SetPreTransmissionDelay(const RTPTime &delay)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+
+	BUILDER_LOCK
+	status = rtcpbuilder.SetPreTransmissionDelay(delay);
+	BUILDER_UNLOCK
+	return status;
+}
+
+RTPTransmissionInfo *RTPSession::GetTransmissionInfo()
+{
+	if (!created)
+		return 0;
+	return rtptrans->GetTransmissionInfo();
+}
+
+void RTPSession::DeleteTransmissionInfo(RTPTransmissionInfo *inf)
+{
+	if (!created)
+		return;
+	rtptrans->DeleteTransmissionInfo(inf);
+}
+
+int RTPSession::Poll()
+{
+	int status;
+	
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	if (usingpollthread)
+		return ERR_RTP_SESSION_USINGPOLLTHREAD;
+	if ((status = rtptrans->Poll()) < 0)
+		return status;
+	return ProcessPolledData();
+}
+
+int RTPSession::WaitForIncomingData(const RTPTime &delay,bool *dataavailable)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	if (usingpollthread)
+		return ERR_RTP_SESSION_USINGPOLLTHREAD;
+	return rtptrans->WaitForIncomingData(delay,dataavailable);
+}
+
+int RTPSession::AbortWait()
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	if (usingpollthread)
+		return ERR_RTP_SESSION_USINGPOLLTHREAD;
+	return rtptrans->AbortWait();
+}
+
+RTPTime RTPSession::GetRTCPDelay()
+{
+	if (!created)
+		return RTPTime(0,0);
+	if (usingpollthread)
+		return RTPTime(0,0);
+
+	SOURCES_LOCK
+	SCHED_LOCK
+	RTPTime t = rtcpsched.GetTransmissionDelay();
+	SCHED_UNLOCK
+	SOURCES_UNLOCK
+	return t;
+}
+
+int RTPSession::BeginDataAccess()
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	SOURCES_LOCK
+	return 0;
+}
+
+bool RTPSession::GotoFirstSource()
+{
+	if (!created)
+		return false;
+	return sources.GotoFirstSource();
+}
+
+bool RTPSession::GotoNextSource()
+{
+	if (!created)
+		return false;
+	return sources.GotoNextSource();
+}
+
+bool RTPSession::GotoPreviousSource()
+{
+	if (!created)
+		return false;
+	return sources.GotoPreviousSource();
+}
+
+bool RTPSession::GotoFirstSourceWithData()
+{
+	if (!created)
+		return false;
+	return sources.GotoFirstSourceWithData();
+}
+
+bool RTPSession::GotoNextSourceWithData()
+{
+	if (!created)
+		return false;
+	return sources.GotoNextSourceWithData();
+}
+
+bool RTPSession::GotoPreviousSourceWithData()
+{
+	if (!created)
+		return false;
+	return sources.GotoPreviousSourceWithData();
+}
+
+RTPSourceData *RTPSession::GetCurrentSourceInfo()
+{
+	if (!created)
+		return 0;
+	return sources.GetCurrentSourceInfo();
+}
+
+RTPSourceData *RTPSession::GetSourceInfo(uint32_t ssrc)
+{
+	if (!created)
+		return 0;
+	return sources.GetSourceInfo(ssrc);
+}
+
+RTPPacket *RTPSession::GetNextPacket()
+{
+	if (!created)
+		return 0;
+	return sources.GetNextPacket();
+}
+
+void RTPSession::DeletePacket(RTPPacket *p)
+{
+	RTPDelete(p,GetMemoryManager());
+}
+
+int RTPSession::EndDataAccess()
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	SOURCES_UNLOCK
+	return 0;
+}
+
+int RTPSession::SetReceiveMode(RTPTransmitter::ReceiveMode m)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	return rtptrans->SetReceiveMode(m);
+}
+
+int RTPSession::AddToIgnoreList(const RTPAddress &addr)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	return rtptrans->AddToIgnoreList(addr);
+}
+
+int RTPSession::DeleteFromIgnoreList(const RTPAddress &addr)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	return rtptrans->DeleteFromIgnoreList(addr);
+}
+
+void RTPSession::ClearIgnoreList()
+{
+	if (!created)
+		return;
+	rtptrans->ClearIgnoreList();
+}
+
+int RTPSession::AddToAcceptList(const RTPAddress &addr)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	return rtptrans->AddToAcceptList(addr);
+}
+
+int RTPSession::DeleteFromAcceptList(const RTPAddress &addr)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+	return rtptrans->DeleteFromAcceptList(addr);
+}
+
+void RTPSession::ClearAcceptList()
+{
+	if (!created)
+		return;
+	rtptrans->ClearAcceptList();
+}
+
+int RTPSession::SetMaximumPacketSize(size_t s)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	if (s < RTP_MINPACKETSIZE)
+		return ERR_RTP_SESSION_MAXPACKETSIZETOOSMALL;
+	
+	int status;
+
+	if ((status = rtptrans->SetMaximumPacketSize(s)) < 0)
+		return status;
+
+	BUILDER_LOCK
+	if ((status = packetbuilder.SetMaximumPacketSize(s)) < 0)
+	{
+		BUILDER_UNLOCK
+		// restore previous max packet size
+		rtptrans->SetMaximumPacketSize(maxpacksize);
+		return status;
+	}
+	if ((status = rtcpbuilder.SetMaximumPacketSize(s)) < 0)
+	{
+		// restore previous max packet size
+		packetbuilder.SetMaximumPacketSize(maxpacksize);
+		BUILDER_UNLOCK
+		rtptrans->SetMaximumPacketSize(maxpacksize);
+		return status;
+	}
+	BUILDER_UNLOCK
+	maxpacksize = s;
+	return 0;
+}
+
+int RTPSession::SetSessionBandwidth(double bw)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+	SCHED_LOCK
+	RTCPSchedulerParams p = rtcpsched.GetParameters();
+	status = p.SetRTCPBandwidth(bw*controlfragment);
+	if (status >= 0)
+	{
+		rtcpsched.SetParameters(p);
+		sessionbandwidth = bw;
+	}
+	SCHED_UNLOCK
+	return status;
+}
+
+int RTPSession::SetTimestampUnit(double u)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+
+	BUILDER_LOCK
+	status = rtcpbuilder.SetTimestampUnit(u);
+	BUILDER_UNLOCK
+	return status;
+}
+
+void RTPSession::SetNameInterval(int count)
+{
+	if (!created)
+		return;
+	BUILDER_LOCK
+	rtcpbuilder.SetNameInterval(count);
+	BUILDER_UNLOCK
+}
+
+void RTPSession::SetEMailInterval(int count)
+{
+	if (!created)
+		return;
+	BUILDER_LOCK
+	rtcpbuilder.SetEMailInterval(count);
+	BUILDER_UNLOCK
+}
+
+void RTPSession::SetLocationInterval(int count)
+{
+	if (!created)
+		return;
+	BUILDER_LOCK
+	rtcpbuilder.SetLocationInterval(count);
+	BUILDER_UNLOCK
+}
+
+void RTPSession::SetPhoneInterval(int count)
+{
+	if (!created)
+		return;
+	BUILDER_LOCK
+	rtcpbuilder.SetPhoneInterval(count);
+	BUILDER_UNLOCK
+}
+
+void RTPSession::SetToolInterval(int count)
+{
+	if (!created)
+		return;
+	BUILDER_LOCK
+	rtcpbuilder.SetToolInterval(count);
+	BUILDER_UNLOCK
+}
+
+void RTPSession::SetNoteInterval(int count)
+{
+	if (!created)
+		return;
+	BUILDER_LOCK
+	rtcpbuilder.SetNoteInterval(count);
+	BUILDER_UNLOCK
+}
+
+int RTPSession::SetLocalName(const void *s,size_t len)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+	BUILDER_LOCK
+	status = rtcpbuilder.SetLocalName(s,len);
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::SetLocalEMail(const void *s,size_t len)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+	BUILDER_LOCK
+	status = rtcpbuilder.SetLocalEMail(s,len);
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::SetLocalLocation(const void *s,size_t len)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+	BUILDER_LOCK
+	status = rtcpbuilder.SetLocalLocation(s,len);
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::SetLocalPhone(const void *s,size_t len)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+	BUILDER_LOCK
+	status = rtcpbuilder.SetLocalPhone(s,len);
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::SetLocalTool(const void *s,size_t len)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+	BUILDER_LOCK
+	status = rtcpbuilder.SetLocalTool(s,len);
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::SetLocalNote(const void *s,size_t len)
+{
+	if (!created)
+		return ERR_RTP_SESSION_NOTCREATED;
+
+	int status;
+	BUILDER_LOCK
+	status = rtcpbuilder.SetLocalNote(s,len);
+	BUILDER_UNLOCK
+	return status;
+}
+
+int RTPSession::ProcessPolledData()
+{
+	RTPRawPacket *rawpack;
+	int status;
+	
+	SOURCES_LOCK
+	while ((rawpack = rtptrans->GetNextPacket()) != 0)
+	{
+		sources.ClearOwnCollisionFlag();
+
+		// since our sources instance also uses the scheduler (analysis of incoming packets)
+		// we'll lock it
+		SCHED_LOCK
+		if ((status = sources.ProcessRawPacket(rawpack,rtptrans,acceptownpackets)) < 0)
+		{
+			SCHED_UNLOCK
+			SOURCES_UNLOCK
+			RTPDelete(rawpack,GetMemoryManager());
+			return status;
+		}
+		SCHED_UNLOCK
+				
+		if (sources.DetectedOwnCollision()) // collision handling!
+		{
+			bool created;
+			
+			if ((status = collisionlist.UpdateAddress(rawpack->GetSenderAddress(),rawpack->GetReceiveTime(),&created)) < 0)
+			{
+				SOURCES_UNLOCK
+				RTPDelete(rawpack,GetMemoryManager());
+				return status;
+			}
+
+			if (created) // first time we've encountered this address, send bye packet and
+			{            // change our own SSRC
+				PACKSENT_LOCK
+				bool hassentpackets = sentpackets;
+				PACKSENT_UNLOCK
+
+				if (hassentpackets)
+				{
+					// Only send BYE packet if we've actually sent data using this
+					// SSRC
+					
+					RTCPCompoundPacket *rtcpcomppack;
+
+					BUILDER_LOCK
+					if ((status = rtcpbuilder.BuildBYEPacket(&rtcpcomppack,0,0,useSR_BYEifpossible)) < 0)
+					{
+						BUILDER_UNLOCK
+						SOURCES_UNLOCK
+						RTPDelete(rawpack,GetMemoryManager());
+						return status;
+					}
+					BUILDER_UNLOCK
+
+					byepackets.push_back(rtcpcomppack);
+					if (byepackets.size() == 1) // was the first packet, schedule a BYE packet (otherwise there's already one scheduled)
+					{
+						SCHED_LOCK
+						rtcpsched.ScheduleBYEPacket(rtcpcomppack->GetCompoundPacketLength());
+						SCHED_UNLOCK
+					}
+				}
+				// bye packet is built and scheduled, now change our SSRC
+				// and reset the packet count in the transmitter
+				
+				BUILDER_LOCK
+				uint32_t newssrc = packetbuilder.CreateNewSSRC(sources);
+				BUILDER_UNLOCK
+					
+				PACKSENT_LOCK
+				sentpackets = false;
+				PACKSENT_UNLOCK
+	
+				// remove old entry in source table and add new one
+
+				if ((status = sources.DeleteOwnSSRC()) < 0)
+				{
+					SOURCES_UNLOCK
+					RTPDelete(rawpack,GetMemoryManager());
+					return status;
+				}
+				if ((status = sources.CreateOwnSSRC(newssrc)) < 0)
+				{
+					SOURCES_UNLOCK
+					RTPDelete(rawpack,GetMemoryManager());
+					return status;
+				}
+			}
+		}
+		RTPDelete(rawpack,GetMemoryManager());
+	}
+
+	SCHED_LOCK
+	RTPTime d = rtcpsched.CalculateDeterministicInterval(false);
+	SCHED_UNLOCK
+	
+	RTPTime t = RTPTime::CurrentTime();
+	double Td = d.GetDouble();
+	RTPTime sendertimeout = RTPTime(Td*sendermultiplier);
+	RTPTime generaltimeout = RTPTime(Td*membermultiplier);
+	RTPTime byetimeout = RTPTime(Td*byemultiplier);
+	RTPTime colltimeout = RTPTime(Td*collisionmultiplier);
+	RTPTime notetimeout = RTPTime(Td*notemultiplier);
+	
+	sources.MultipleTimeouts(t,sendertimeout,byetimeout,generaltimeout,notetimeout);
+	collisionlist.Timeout(t,colltimeout);
+	
+	// We'll check if it's time for RTCP stuff
+
+	SCHED_LOCK
+	bool istime = rtcpsched.IsTime();
+	SCHED_UNLOCK
+	
+	if (istime)
+	{
+		RTCPCompoundPacket *pack;
+	
+		// we'll check if there's a bye packet to send, or just a normal packet
+
+		if (byepackets.empty())
+		{
+			BUILDER_LOCK
+			if ((status = rtcpbuilder.BuildNextPacket(&pack)) < 0)
+			{
+				BUILDER_UNLOCK
+				SOURCES_UNLOCK
+				return status;
+			}
+			BUILDER_UNLOCK
+			if ((status = rtptrans->SendRTCPData(pack->GetCompoundPacketData(),pack->GetCompoundPacketLength())) < 0)
+			{
+				SOURCES_UNLOCK
+				RTPDelete(pack,GetMemoryManager());
+				return status;
+			}
+		
+			PACKSENT_LOCK
+			sentpackets = true;
+			PACKSENT_UNLOCK
+
+			OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering
+		}
+		else
+		{
+			pack = *(byepackets.begin());
+			byepackets.pop_front();
+			
+			if ((status = rtptrans->SendRTCPData(pack->GetCompoundPacketData(),pack->GetCompoundPacketLength())) < 0)
+			{
+				SOURCES_UNLOCK
+				RTPDelete(pack,GetMemoryManager());
+				return status;
+			}
+			
+			PACKSENT_LOCK
+			sentpackets = true;
+			PACKSENT_UNLOCK
+
+			OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering
+			
+			if (!byepackets.empty()) // more bye packets to send, schedule them
+			{
+				SCHED_LOCK
+				rtcpsched.ScheduleBYEPacket((*(byepackets.begin()))->GetCompoundPacketLength());
+				SCHED_UNLOCK
+			}
+		}
+		
+		SCHED_LOCK
+		rtcpsched.AnalyseOutgoing(*pack);
+		SCHED_UNLOCK
+
+		RTPDelete(pack,GetMemoryManager());
+	}
+	SOURCES_UNLOCK
+	return 0;
+}
+
+int RTPSession::CreateCNAME(uint8_t *buffer,size_t *bufferlength,bool resolve)
+{
+#ifndef WIN32
+	bool gotlogin = true;
+#ifdef RTP_SUPPORT_GETLOGINR
+	buffer[0] = 0;
+	if (getlogin_r((char *)buffer,*bufferlength) != 0)
+		gotlogin = false;
+	else
+	{
+		if (buffer[0] == 0)
+			gotlogin = false;
+	}
+	
+	if (!gotlogin) // try regular getlogin
+	{
+		char *loginname = getlogin();
+		if (loginname == 0)
+			gotlogin = false;
+		else
+			strncpy((char *)buffer,loginname,*bufferlength);
+	}
+#else
+	char *loginname = getlogin();
+	if (loginname == 0)
+		gotlogin = false;
+	else
+		strncpy((char *)buffer,loginname,*bufferlength);
+#endif // RTP_SUPPORT_GETLOGINR
+	if (!gotlogin)
+	{
+		char *logname = getenv("LOGNAME");
+		if (logname == 0)
+			return ERR_RTP_SESSION_CANTGETLOGINNAME;
+		strncpy((char *)buffer,logname,*bufferlength);
+	}
+#else // Win32 version
+
+#ifndef _WIN32_WCE
+	DWORD len = *bufferlength;
+	if (!GetUserName((LPTSTR)buffer,&len))
+#if (defined(_MSC_VER) && _MSC_VER >= 1400 ) // Check if we can use the secure strncpy_s
+		strncpy_s((char *)buffer,*bufferlength,"unknown",_TRUNCATE);
+#else
+		strncpy((char *)buffer,"unknown",*bufferlength);
+#endif // Less secure version
+
+#else 
+	strncpy((char *)buffer,"unknown",*bufferlength);
+#endif // _WIN32_WCE
+	
+#endif // WIN32
+	buffer[*bufferlength-1] = 0;
+
+	size_t offset = strlen((const char *)buffer);
+	if (offset < (*bufferlength-1))
+		buffer[offset] = (uint8_t)'@';
+	offset++;
+
+	size_t buflen2 = *bufferlength-offset;
+	int status;
+	
+	if (resolve)
+	{
+		if ((status = rtptrans->GetLocalHostName(buffer+offset,&buflen2)) < 0)
+			return status;
+		*bufferlength = buflen2+offset;
+	}
+	else
+	{
+		char hostname[1024];
+		
+#if defined(WIN32) && !defined(_WIN32_WCE) && (defined(_MSC_VER) && _MSC_VER >= 1400 ) // Check if we can use the secure strncpy_s
+		strncpy_s(hostname,1024,"localhost",_TRUNCATE); // just in case gethostname fails
+#else
+		strncpy(hostname,"localhost",1024); // just in case gethostname fails
+#endif
+		gethostname(hostname,1024);
+#if defined(WIN32) && !defined(_WIN32_WCE) && (defined(_MSC_VER) && _MSC_VER >= 1400 ) // Check if we can use the secure strncpy_s
+		strncpy_s((char *)(buffer+offset),buflen2,hostname,_TRUNCATE);
+#else
+		strncpy((char *)(buffer+offset),hostname,buflen2);
+#endif
+		*bufferlength = offset+strlen(hostname);
+	}
+	if (*bufferlength > RTCP_SDES_MAXITEMLENGTH)
+		*bufferlength = RTCP_SDES_MAXITEMLENGTH;
+	return 0;
+}
+
+RTPRandom *RTPSession::GetRandomNumberGenerator(RTPRandom *r)
+{
+	RTPRandom *rnew = 0;
+
+	if (r == 0)
+	{
+#if defined(WIN32) || defined(_WIN32_WCE)
+		RTPRandomRandS *rnew2 = new RTPRandomRandS();
+#else
+		RTPRandomURandom *rnew2 = new RTPRandomURandom();
+#endif // WIN32 || _WIN32_WCE
+
+		if (rnew2->Init() < 0) // fall back to rand48
+		{
+			delete rnew2;
+			rnew = new RTPRandomRand48();
+		}
+		else
+			rnew = rnew2;
+
+		deletertprnd = true;
+	}
+	else
+	{
+		rnew = r;
+		deletertprnd = false;
+	}
+
+	return rnew;
+}
+
+#ifdef RTPDEBUG
+void RTPSession::DumpSources()
+{
+	BeginDataAccess();
+	std::cout << "----------------------------------------------------------------" << std::endl;
+	sources.Dump();
+	EndDataAccess();
+}
+
+void RTPSession::DumpTransmitter()
+{
+	if (created)
+		rtptrans->Dump();
+}
+#endif // RTPDEBUG
+
+} // end namespace
+

+ 581 - 0
lib/common/jrtplib/src/rtpsession.h

@@ -0,0 +1,581 @@
+/*
+
+  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.h"
+#include "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
+

+ 88 - 0
lib/common/jrtplib/src/rtpsessionparams.cpp

@@ -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
+

+ 248 - 0
lib/common/jrtplib/src/rtpsessionparams.h

@@ -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
+

+ 114 - 0
lib/common/jrtplib/src/rtpsessionsources.cpp

@@ -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
+

+ 84 - 0
lib/common/jrtplib/src/rtpsessionsources.h

@@ -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

+ 500 - 0
lib/common/jrtplib/src/rtpsourcedata.cpp

@@ -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
+
+

+ 480 - 0
lib/common/jrtplib/src/rtpsourcedata.h

@@ -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; }
+
+	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
+

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio