├── .gitignore ├── README.md ├── build ├── CMakeLists.txt ├── Triplet.cmake ├── build.sh ├── build_linux_dependencies.sh ├── build_mac_dependencies.sh ├── clean.sh ├── debug.sh └── release.sh ├── html ├── signaling.js ├── style.css ├── test_sending.html └── test_signaling.html ├── include ├── dtls │ ├── Context.h │ └── Parser.h ├── ice │ ├── Agent.h │ ├── Candidate.h │ ├── Stream.h │ └── Utils.h ├── rtc │ └── Connection.h ├── rtp │ ├── PacketVP8.h │ ├── ReaderVP8.h │ └── WriterVP8.h ├── sdp │ ├── Reader.h │ ├── SDP.h │ ├── Types.h │ ├── Utils.h │ └── Writer.h ├── signaling │ ├── Room.h │ ├── Signaling.h │ └── SignalingSettings.h ├── srtp │ └── ParserSRTP.h ├── stun │ ├── Attribute.h │ ├── Message.h │ ├── Reader.h │ ├── Types.h │ ├── Utils.h │ └── Writer.h └── video │ ├── AggregatorVP8.h │ ├── DecoderVP8.h │ ├── EncoderSettings.h │ ├── EncoderVP8.h │ └── WriterIVF.h └── src ├── dtls ├── Context.cpp └── Parser.cpp ├── ice ├── Agent.cpp ├── Candidate.cpp ├── Stream.cpp └── Utils.cpp ├── rtc └── Connection.cpp ├── rtp ├── PacketVP8.cpp ├── ReaderVP8.cpp └── WriterVP8.cpp ├── sdp ├── Reader.cpp ├── SDP.cpp ├── Types.cpp ├── Utils.cpp └── Writer.cpp ├── signaling ├── Room.cpp ├── Signaling.cpp └── SignalingSettings.cpp ├── srtp └── ParserSRTP.cpp ├── stun ├── Attribute.cpp ├── Message.cpp ├── Reader.cpp ├── Types.cpp ├── Utils.cpp └── Writer.cpp ├── test_webrtc_dtls.cpp ├── test_webrtc_extract_keying_info_for_srtp.cpp ├── test_webrtc_hmac_sha1.cpp ├── test_webrtc_ice.cpp ├── test_webrtc_ice_agent.cpp ├── test_webrtc_libwebsockets.cpp ├── test_webrtc_mongoose.cpp ├── test_webrtc_openssl_load_key_and_cert.cpp ├── test_webrtc_signaling.cpp ├── test_webrtc_ssl_fingerprint.cpp ├── test_webrtc_stun_message_fingerprint.cpp ├── test_webrtc_stun_message_integrity.cpp ├── test_webrtc_video_encoder.cpp ├── test_webrtc_zlib_crc32.cpp └── video ├── AggregatorVP8.cpp ├── DecoderVP8.cpp ├── EncoderSettings.cpp ├── EncoderVP8.cpp └── WriterIVF.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | install 2 | extern 3 | build 4 | shared 5 | 6 | ########################################################################################### 7 | 8 | *.com 9 | *.class 10 | *.dll 11 | *.exe 12 | *.o 13 | *.so 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | *.log 23 | *.sql 24 | *.sqlite 25 | .DS_Store 26 | .DS_Store? 27 | ._* 28 | .Spotlight-V100 29 | .Trashes 30 | ehthumbs.db 31 | Thumbs.db -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ````text 2 | 3 | +---------------+ 4 | | | 5 | +--> + dtls::Context | 6 | | | | 7 | | +---------------+ 8 | | 9 | +---------+ | +---------+ 10 | | | | | | 11 | | Agent + ---+--> + Stream + 12 | | | | | 13 | +---------+ +----+----+ 14 | | 15 | | 16 | V 17 | +------+------+ 18 | | | 19 | | Candidate + 20 | | | 21 | +------+------+ +---------------+ 22 | | | | 23 | +------------------------------> + dtls::Parser | 24 | | | | 25 | | +---------------+ 26 | | 27 | | +---------------------+ 28 | | | | 29 | +------------------------------> + rtc::ConnectionUDP | 30 | | | | 31 | | +---------------------+ 32 | | 33 | | +---------------------+ 34 | | | | 35 | +------------------------------> + stun::Reader | 36 | | | 37 | +---------------------+ 38 | 39 | 40 | 41 | ```` -------------------------------------------------------------------------------- /build/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | include(${CMAKE_CURRENT_LIST_DIR}/Triplet.cmake) 4 | 5 | set(app webrtc) 6 | set(lib webrtc) 7 | set(sd ${CMAKE_CURRENT_LIST_DIR}/../src/) 8 | set(id ${CMAKE_CURRENT_LIST_DIR}/../include/) 9 | set(debug "") 10 | 11 | if(CMAKE_BUILD_TYPE STREQUAL Debug) 12 | set(app "${app}_debug") 13 | set(debug "debug") 14 | endif() 15 | 16 | #add_definitions("-fsanitize-address-zero-base-shadow") 17 | #add_definitions("-fsanitize=address") 18 | 19 | add_definitions(-DUSE_WEBSOCKET) 20 | 21 | if (UNIX AND NOT APPLE) 22 | add_definitions("-std=c++0x") 23 | endif() 24 | 25 | include_directories( 26 | ${CMAKE_CURRENT_LIST_DIR}/../src 27 | ${CMAKE_CURRENT_LIST_DIR}/../include 28 | ${extern_include_dir} 29 | ${CMAKE_CURRENT_LIST_DIR}/../extern/tinylib/src 30 | ) 31 | 32 | set(lib_sources 33 | ${sd}/sdp/SDP.cpp 34 | ${sd}/sdp/Utils.cpp 35 | ${sd}/sdp/Types.cpp 36 | ${sd}/sdp/Reader.cpp 37 | ${sd}/sdp/Writer.cpp 38 | ${sd}/stun/Reader.cpp 39 | ${sd}/stun/Writer.cpp 40 | ${sd}/stun/Message.cpp 41 | ${sd}/stun/Attribute.cpp 42 | ${sd}/stun/Types.cpp 43 | ${sd}/stun/Utils.cpp 44 | ${sd}/ice/Utils.cpp 45 | ${sd}/ice/Candidate.cpp 46 | ${sd}/ice/Agent.cpp 47 | ${sd}/ice/Stream.cpp 48 | ${sd}/dtls/Context.cpp 49 | ${sd}/dtls/Parser.cpp 50 | ${sd}/rtc/Connection.cpp 51 | ${sd}/srtp/ParserSRTP.cpp 52 | ${sd}/rtp/ReaderVP8.cpp 53 | ${sd}/rtp/WriterVP8.cpp 54 | ${sd}/rtp/PacketVP8.cpp 55 | ${sd}/video/AggregatorVP8.cpp 56 | ${sd}/video/WriterIVF.cpp 57 | ${sd}/video/EncoderVP8.cpp 58 | ${sd}/video/DecoderVP8.cpp 59 | ${sd}/video/EncoderSettings.cpp 60 | 61 | # signaling 62 | ${sd}/signaling/Signaling.cpp 63 | ${sd}/signaling/Room.cpp 64 | ${sd}/signaling/SignalingSettings.cpp 65 | ${extern_source_dir}/mongoose.c 66 | ${extern_source_dir}/net_skeleton.c 67 | ${extern_source_dir}/ssl_wrapper.c 68 | ) 69 | 70 | set(lib_headers 71 | ${id} 72 | ) 73 | 74 | set(app_libs 75 | ${extern_lib_dir}/libssl.a # for hmac/sha/ssl 76 | ${extern_lib_dir}/libcrypto.a # for hmac/sha/ssl 77 | ${extern_lib_dir}/libuv.a # for networking 78 | ${extern_lib_dir}/libz.a # for crc32 79 | ${extern_lib_dir}/libsrtp.a # used to handle SRTP packets. 80 | ${extern_lib_dir}/libvpx.a # encoding/decoding vp8 81 | ${extern_lib_dir}/libvideogenerator.a # used for test purposes; 82 | ) 83 | 84 | if (UNIX AND NOT APPLE) 85 | list(APPEND app_libs 86 | pthread 87 | dl 88 | ) 89 | endif() 90 | 91 | set(webrtc_sources ${lib_sources}) 92 | set(webrtc_libs ${app_libs}) 93 | 94 | macro(create_test name) 95 | add_executable("test_webrtc_${name}${debug}" ${sd}/test_webrtc_${name}.cpp) 96 | target_link_libraries("test_webrtc_${name}${debug}" ${lib} ${app_libs}) 97 | install(TARGETS "test_webrtc_${name}${debug}" DESTINATION bin) 98 | endmacro() 99 | 100 | add_library(${lib} STATIC ${lib_sources}) 101 | install(TARGETS ${lib} ARCHIVE DESTINATION lib) 102 | install(DIRECTORY ${lib_headers} DESTINATION include) 103 | 104 | # temporary disable the webrtc tests 105 | create_test(ice) 106 | create_test(ssl_fingerprint) 107 | create_test(hmac_sha1) 108 | create_test(stun_message_integrity) 109 | create_test(zlib_crc32) 110 | create_test(stun_message_fingerprint) 111 | create_test(openssl_load_key_and_cert) 112 | create_test(ice_agent) 113 | create_test(dtls) 114 | create_test(extract_keying_info_for_srtp) 115 | create_test(video_encoder) 116 | create_test(mongoose) 117 | create_test(signaling) 118 | -------------------------------------------------------------------------------- /build/Triplet.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | # ${tri_arch} - x86_64, i386 4 | # ${tri_compiler} - clang, gcc, vs2010, vs2012 5 | # ${tri_platform} - mac, win, unix 6 | # ${tri_triplet} - ${tri_platform}-${tri_compiler}-${tri_arch} 7 | # ${install_dir} - the install prefix 8 | # ${extern_source_dir} - path to the source directory inside extern/${tri_triplet}/ 9 | # ${extern_lib_dir} - path to the extern libraries (root) 10 | # ${extern_include_dir} - include directories in for the extern libraries 11 | 12 | if(NOT ROXLU_USE_32BIT) 13 | set(tri_arch "x86_64") 14 | else() 15 | set(tri_arch "i386") 16 | endif() 17 | 18 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") 19 | set(tri_compiler "clang") 20 | elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 21 | set(tri_compiler "gcc") 22 | elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 23 | if(MSVC10) 24 | set(tri_compiler "vs2010") 25 | else() 26 | set(tri_compiler "vs2012") 27 | endif() 28 | endif() 29 | 30 | if(APPLE) 31 | set(tri_platform "mac") 32 | elseif(WIN32) 33 | set(tri_platform "win") 34 | else() 35 | set(tri_platform "linux") 36 | endif() 37 | 38 | set(tri_triplet "${tri_platform}-${tri_compiler}-${tri_arch}") 39 | 40 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") 41 | set(tri_triplet "${tri_triplet}d") 42 | endif() 43 | 44 | set(install_dir ${CMAKE_CURRENT_LIST_DIR}/../install/${tri_triplet}) 45 | set(extern_source_dir ${CMAKE_CURRENT_LIST_DIR}/../extern/${tri_triplet}/src/) 46 | set(extern_lib_dir ${CMAKE_CURRENT_LIST_DIR}/../extern/${tri_triplet}/lib/) 47 | set(extern_include_dir ${CMAKE_CURRENT_LIST_DIR}/../extern/${tri_triplet}/include) 48 | 49 | if (NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 50 | set(CMAKE_INSTALL_PREFIX ${install_dir}) 51 | endif() 52 | 53 | message(STATUS "Building for ${tri_triplet}") 54 | message(STATUS "Extern include dir: ${extern_include_dir}") 55 | -------------------------------------------------------------------------------- /build/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ ! -d build.release ] ; then 4 | mkdir build.release 5 | fi 6 | 7 | cd build.release 8 | cmake -DCMAKE_BUILD_TYPE=Release ../ 9 | cmake --build . --target install 10 | 11 | -------------------------------------------------------------------------------- /build/build_linux_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -x 3 | d=${PWD} 4 | sd=${d}/linux-sources 5 | bd=${d}/../extern/linux-gcc-x86_64 6 | 7 | export PATH=${PATH}:${bd}/bin/ 8 | export CFLAGS="-I\"${bd}/include\"" 9 | export LDFLAGS="-L\"${bd}/lib\"" 10 | 11 | # ----------------------------------------------------------------------- # 12 | # D O W N L O A D D E P E N D E N C I E S 13 | # ----------------------------------------------------------------------- # 14 | 15 | # Create source dir 16 | if [ ! -d ${sd} ] ; then 17 | mkdir -p ${sd} 18 | fi 19 | 20 | if [ ! -d ${bd}/src ] ; then 21 | mkdir -p ${bd}/src 22 | fi 23 | 24 | # Download openssl 25 | if [ ! -d ${sd}/openssl ] ; then 26 | cd ${sd} 27 | if [ ! -f openssl.tar.gz ] ; then 28 | curl -o openssl.tar.gz http://www.openssl.org/source/openssl-1.0.1i.tar.gz 29 | tar -zxvf openssl.tar.gz 30 | fi 31 | mv openssl-1.0.1i openssl 32 | fi 33 | 34 | # Download libuv 35 | if [ ! -d ${sd}/libuv ] ; then 36 | cd ${sd} 37 | git clone https://github.com/joyent/libuv.git libuv 38 | fi 39 | 40 | # Download libz 41 | if [ ! -d ${sd}/zlib ] ; then 42 | cd ${sd} 43 | if [ ! -f libz.tar.gz ] ; then 44 | curl -o libz.tar.gz http://zlib.net/zlib-1.2.8.tar.gz 45 | tar -zxvf libz.tar.gz 46 | fi 47 | mv zlib-1.2.8 zlib 48 | fi 49 | 50 | # Download libsrtp 51 | if [ ! -d ${sd}/libsrtp ] ; then 52 | cd ${sd} 53 | git clone https://github.com/cisco/libsrtp.git libsrtp 54 | fi 55 | 56 | # Download libvpx 57 | if [ ! -d ${sd}/libvpx ] ; then 58 | cd ${sd} 59 | git clone https://chromium.googlesource.com/webm/libvpx libvpx 60 | fi 61 | 62 | # Download libvideogenerator 63 | if [ ! -d ${sd}/libvideogenerator ] ; then 64 | cd ${sd} 65 | git clone git@github.com:roxlu/video_generator.git libvideogenerator 66 | fi 67 | 68 | # Download yasm, needed for libvpx 69 | if [ ! -d ${sd}/yasm ] ; then 70 | cd ${sd} 71 | curl -o yasm.tar.gz http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz 72 | tar -zxvf yasm.tar.gz 73 | mv yasm-1.3.0 yasm 74 | fi 75 | 76 | # Download mongoose (signaling) 77 | if [ ! -d ${sd}/mongoose ] ; then 78 | cd ${sd} 79 | git clone https://github.com/cesanta/mongoose.git mongoose 80 | fi 81 | 82 | if [ ! -f ${bd}/src/mongoose.c ] ; then 83 | cp ${sd}/mongoose/mongoose.c ${bd}/src/ 84 | cp ${sd}/mongoose/mongoose.h ${bd}/include/ 85 | fi 86 | 87 | # Download net_skeleton (signaling) 88 | if [ ! -d ${sd}/net_skeleton ] ; then 89 | cd ${sd} 90 | git clone https://github.com/cesanta/net_skeleton.git net_skeleton 91 | fi 92 | 93 | if [ ! -f ${bd}/src/net_skeleton.c ] ; then 94 | cp ${sd}/net_skeleton/net_skeleton.c ${bd}/src/ 95 | cp ${sd}/net_skeleton/net_skeleton.h ${bd}/include/ 96 | fi 97 | 98 | # Download ssl_wrapper (signaling) 99 | if [ ! -d ${sd}/ssl_wrapper ] ; then 100 | cd ${sd} 101 | git clone https://github.com/cesanta/ssl_wrapper.git ssl_wrapper 102 | fi 103 | 104 | if [ ! -f ${bd}/src/ssl_wrapper.c ] ; then 105 | cp ${sd}/ssl_wrapper/ssl_wrapper.c ${bd}/src/ 106 | cp ${sd}/ssl_wrapper/ssl_wrapper.h ${bd}/include/ 107 | fi 108 | 109 | # ----------------------------------------------------------------------- # 110 | # C O M P I L E D E P E N D E N C I E S 111 | # ----------------------------------------------------------------------- # 112 | 113 | # Compile openSSL 114 | if [ ! -f ${bd}/lib/libssl.a ] ; then 115 | cd ${sd}/openssl 116 | ./Configure --prefix=${bd} linux-x86_64 117 | make clean 118 | make 119 | make install 120 | fi 121 | 122 | # Compile libuv 123 | if [ ! -f ${bd}/lib/libuv.a ] ; then 124 | cd ${sd}/libuv 125 | ./autogen.sh 126 | ./configure --prefix=${bd} --enable-static 127 | make 128 | make install 129 | fi 130 | 131 | # Compile zlib 132 | if [ ! -f ${bd}/lib/libz.a ] ; then 133 | cd ${sd}/zlib 134 | ./configure --prefix=${bd} --static --64 135 | make 136 | make install 137 | fi 138 | 139 | # Compile libsrtp 140 | if [ ! -f ${bd}/lib/libsrtp.a ] ; then 141 | cd ${sd}/libsrtp 142 | ./configure --prefix=${bd} 143 | make 144 | make install 145 | fi 146 | 147 | # Compile yasm 148 | if [ ! -f ${bd}/bin/yasm ] ; then 149 | cd ${sd}/yasm 150 | ./configure --prefix=${bd} 151 | make 152 | make install 153 | fi 154 | 155 | # Compile libvpx 156 | if [ ! -f ${bd}/lib/libvpx.a ] ; then 157 | cd ${sd}/libvpx 158 | ./configure --prefix=${bd} --as=yasm --disable-shared --enable-static 159 | make 160 | make install 161 | fi 162 | 163 | # Compile libvideogenerator 164 | if [ ! -f ${bd}/lib/libvideogenerator.a ] ; then 165 | cd ${sd}/libvideogenerator/build 166 | cmake -DCMAKE_INSTALL_PREFIX=${bd} 167 | cmake --build . --target install 168 | fi 169 | 170 | 171 | -------------------------------------------------------------------------------- /build/build_mac_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -x 3 | d=${PWD} 4 | sd=${d}/mac-sources 5 | bd=${d}/../extern/mac-clang-x86_64 6 | 7 | export PATH=${PATH}:${bd}/bin/:${sd}/gyp/ 8 | export CFLAGS="-I\"${bd}/include\"" 9 | export LDFLAGS="-L\"${bd}/lib\"" 10 | 11 | # ----------------------------------------------------------------------- # 12 | # D O W N L O A D D E P E N D E N C I E S 13 | # ----------------------------------------------------------------------- # 14 | if [ ! -d ${sd} ] ; then 15 | mkdir -p ${sd} 16 | fi 17 | 18 | if [ ! -d ${bd}/src ] ; then 19 | mkdir ${bd}/src 20 | fi 21 | 22 | # Download autoconf and friends (for libuv) 23 | if [ ! -d ${sd}/autoconf ] ; then 24 | cd ${sd} 25 | curl -o autoconf.tar.gz http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz 26 | tar -zxvf autoconf.tar.gz 27 | mv autoconf-2.69 autoconf 28 | fi 29 | 30 | # Download libtool 31 | if [ ! -d ${sd}/libtool ] ; then 32 | cd ${sd} 33 | curl -o libtool.tar.gz http://ftp.gnu.org/gnu/libtool/libtool-2.4.2.tar.gz 34 | tar -zxvf libtool.tar.gz 35 | mv libtool-2.4.2 libtool 36 | fi 37 | 38 | # Download automake 39 | if [ ! -d ${sd}/automake ] ; then 40 | cd ${sd} 41 | curl -o automake.tar.gz http://ftp.gnu.org/gnu/automake/automake-1.14.tar.gz 42 | tar -zxvf automake.tar.gz 43 | mv automake-1.14 automake 44 | fi 45 | 46 | # Download openssl 47 | if [ ! -d ${sd}/openssl ] ; then 48 | cd ${sd} 49 | if [ ! -f openssl.tar.gz ] ; then 50 | curl -o openssl.tar.gz http://www.openssl.org/source/openssl-1.0.1i.tar.gz 51 | tar -zxvf openssl.tar.gz 52 | fi 53 | mv openssl-1.0.1i openssl 54 | fi 55 | 56 | # Download libuv 57 | if [ ! -d ${sd}/libuv ] ; then 58 | cd ${sd} 59 | git clone https://github.com/joyent/libuv.git libuv 60 | fi 61 | 62 | # Download gyp for libuv 63 | if [ ! -d ${sd}/libuv/build/gyp ] ; then 64 | cd ${sd}/libuv 65 | git clone https://git.chromium.org/external/gyp.git build/gyp 66 | fi 67 | 68 | # Download libz 69 | if [ ! -d ${sd}/zlib ] ; then 70 | cd ${sd} 71 | if [ ! -f libz.tar.gz ] ; then 72 | curl -o libz.tar.gz http://zlib.net/zlib-1.2.8.tar.gz 73 | tar -zxvf libz.tar.gz 74 | fi 75 | mv zlib-1.2.8 zlib 76 | fi 77 | 78 | # Download libsrtp 79 | if [ ! -d ${sd}/libsrtp ] ; then 80 | cd ${sd} 81 | git clone https://github.com/cisco/libsrtp.git libsrtp 82 | fi 83 | 84 | # Download libvpx 85 | if [ ! -d ${sd}/libvpx ] ; then 86 | cd ${sd} 87 | git clone https://chromium.googlesource.com/webm/libvpx libvpx 88 | fi 89 | 90 | # Download libvideogenerator 91 | if [ ! -d ${sd}/libvideogenerator ] ; then 92 | cd ${sd} 93 | git clone git@github.com:roxlu/video_generator.git libvideogenerator 94 | fi 95 | 96 | # Download yasm, needed for libvpx 97 | if [ ! -d ${sd}/yasm ] ; then 98 | cd ${sd} 99 | curl -o yasm.tar.gz http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz 100 | tar -zxvf yasm.tar.gz 101 | mv yasm-1.3.0 yasm 102 | fi 103 | 104 | # Download mongoose (signaling) 105 | if [ ! -d ${sd}/mongoose ] ; then 106 | cd ${sd} 107 | git clone https://github.com/cesanta/mongoose.git mongoose 108 | fi 109 | 110 | if [ ! -f ${bd}/src/mongoose.c ] ; then 111 | cp ${sd}/mongoose/mongoose.c ${bd}/src/ 112 | cp ${sd}/mongoose/mongoose.h ${bd}/include/ 113 | fi 114 | 115 | # Download net_skeleton (signaling) 116 | if [ ! -d ${sd}/net_skeleton ] ; then 117 | cd ${sd} 118 | git clone https://github.com/cesanta/net_skeleton.git net_skeleton 119 | fi 120 | 121 | if [ ! -f ${bd}/src/net_skeleton.c ] ; then 122 | cp ${sd}/net_skeleton/net_skeleton.c ${bd}/src/ 123 | cp ${sd}/net_skeleton/net_skeleton.h ${bd}/include/ 124 | fi 125 | 126 | # Download ssl_wrapper (signaling) 127 | if [ ! -d ${sd}/ssl_wrapper ] ; then 128 | cd ${sd} 129 | git clone https://github.com/cesanta/ssl_wrapper.git ssl_wrapper 130 | fi 131 | 132 | if [ ! -f ${bd}/src/ssl_wrapper.c ] ; then 133 | cp ${sd}/ssl_wrapper/ssl_wrapper.c ${bd}/src/ 134 | cp ${sd}/ssl_wrapper/ssl_wrapper.h ${bd}/include/ 135 | fi 136 | 137 | # Cleanup some files we don't need anymore. 138 | if [ -f ${sd}/autoconf.tar.gz ] ; then 139 | rm ${sd}/autoconf.tar.gz 140 | fi 141 | if [ -f ${sd}/automake.tar.gz ] ; then 142 | rm ${sd}/automake.tar.gz 143 | fi 144 | if [ -f ${sd}/libtool.tar.gz ] ; then 145 | rm ${sd}/libtool.tar.gz 146 | fi 147 | if [ -f ${sd}/libz.tar.gz ] ; then 148 | rm ${sd}/libz.tar.gz 149 | fi 150 | if [ -f ${sd}/openssl.tar.gz ] ; then 151 | rm ${sd}/openssl.tar.gz 152 | fi 153 | if [ -f ${sd}/yasm.tar.gz ] ; then 154 | rm ${sd}/yasm.tar.gz 155 | fi 156 | 157 | # ----------------------------------------------------------------------- # 158 | # C O M P I L E D E P E N D E N C I E S 159 | # ----------------------------------------------------------------------- # 160 | 161 | # Compile autoconf 162 | if [ ! -f ${bd}/bin/autoconf ] ; then 163 | cd ${sd}/autoconf 164 | ./configure --prefix=${bd} 165 | make 166 | make install 167 | fi 168 | 169 | # Compile libtool 170 | if [ ! -f ${bd}/bin/libtool ] ; then 171 | cd ${sd}/libtool 172 | ./configure --prefix=${bd} 173 | make 174 | make install 175 | fi 176 | 177 | if [ ! -f ${bd}/bin/automake ] ; then 178 | cd ${sd}/automake 179 | ./configure --prefix=${bd} 180 | make 181 | make install 182 | fi 183 | 184 | # Compile openSSL 185 | if [ ! -f ${bd}/lib/libssl.a ] ; then 186 | cd ${sd}/openssl 187 | ./Configure --prefix=${bd} darwin64-x86_64-cc 188 | make clean 189 | make 190 | make install 191 | fi 192 | 193 | # Compile libuv 194 | if [ ! -f ${bd}/lib/libuv.a ] ; then 195 | cd ${sd}/libuv 196 | ./gyp_uv.py -f xcode 197 | xcodebuild -ARCHS="x86_64" -project uv.xcodeproj -configuration Release -target All 198 | cp ${sd}/libuv/build/Release/libuv.a ${bd}/lib/ 199 | cp ${sd}/libuv/include/*.h ${bd}/include/ 200 | fi 201 | 202 | # Compile zlib 203 | if [ ! -f ${bd}/lib/libz.a ] ; then 204 | cd ${sd}/zlib 205 | ./configure --prefix=${bd} --static --64 206 | make 207 | make install 208 | fi 209 | 210 | # Compile libsrtp 211 | if [ ! -f ${bd}/lib/libsrtp.a ] ; then 212 | cd ${sd}/libsrtp 213 | ./configure --prefix=${bd} 214 | make 215 | make install 216 | fi 217 | 218 | # Compile yasm 219 | if [ ! -f ${bd}/bin/yasm ] ; then 220 | cd ${sd}/yasm 221 | ./configure --prefix=${bd} 222 | make 223 | make install 224 | fi 225 | 226 | # Compile libvpx 227 | if [ ! -f ${bd}/lib/libvpx.a ] ; then 228 | cd ${sd}/libvpx 229 | ./configure --prefix=${bd} --as=yasm --disable-shared --enable-static 230 | make 231 | make install 232 | fi 233 | 234 | # Compile libvideogenerator 235 | if [ ! -f ${bd}/lib/libvideogenerator.a ] ; then 236 | cd ${sd}/libvideogenerator/build 237 | cmake -DCMAKE_INSTALL_PREFIX=${bd} 238 | cmake --build . --target install 239 | fi 240 | 241 | -------------------------------------------------------------------------------- /build/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -d build ] ; then 4 | rm -r build 5 | fi 6 | 7 | if [ -d build.release ] ; then 8 | rm -r build.release 9 | fi 10 | 11 | if [ -d build.debug ] ; then 12 | rm -r build.debug 13 | fi 14 | -------------------------------------------------------------------------------- /build/debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ ! -d build.debug ] ; then 4 | mkdir build.debug 5 | fi 6 | 7 | cd build.debug 8 | cmake -DCMAKE_BUILD_TYPE=Debug ../ 9 | cmake --build . --target install 10 | cd ./../../install/mac-clang-x86_64d/bin/ 11 | lldb ./test_extract_keying_info_for_srtpdebug 12 | -------------------------------------------------------------------------------- /build/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | d=${PWD} 4 | 5 | if [ ! -d build.release ] ; then 6 | mkdir build.release 7 | fi 8 | 9 | if [ "$(uname)" == "Darwin" ] ; then 10 | if [ ! -d ${d}/../extern/mac-clang-x86_64 ] ; then 11 | ./build_mac_dependencies.sh 12 | cd build.release 13 | fi 14 | else 15 | if [ ! -d ${d}/../extern/linux-gcc-x86_x64 ] ; then 16 | ./build_linux_dependencies.sh 17 | fi 18 | fi 19 | 20 | cd build.release 21 | cmake -DCMAKE_BUILD_TYPE=Release ../ 22 | cmake --build . --target install 23 | 24 | if [ "$(uname)" == "Darwin" ] ; then 25 | export PATH=${d}/../install/mac-clang-x86_64/bin/:${PATH} 26 | cd ./../../install/mac-clang-x86_64/bin/ 27 | if [ ! -f server-key.pem ] ; then 28 | openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -subj "/C=/ST=/L=/O=/CN=roxlu.com" -keyout server-key.pem -out server-cert.pem 29 | fi 30 | else 31 | export PATH=${d}/../install/linux-gcc-x86_64/bin/:${PATH} 32 | cd ./../../install/linux-gcc-x86_64/bin/ 33 | if [ ! -f server-key.pem ] ; then 34 | openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -subj "/C=/ST=/L=/O=/CN=roxlu.com" -keyout server-key.pem -out server-cert.pem 35 | fi 36 | fi 37 | 38 | #./test_ice 39 | #./test_ssl_fingerprint 40 | #./test_zlib_crc32 41 | #./test_hmac_sha1 42 | #./test_stun_message_integrity 43 | #./test_stun_message_fingerprint 44 | #./test_openssl_load_key_and_cert 45 | #./test_libwebsockets 46 | ./test_ice_agent 47 | #./test_extract_keying_info_for_srtp 48 | #./test_video_encoder 49 | #./test_mongoose 50 | #./test_signaling 51 | -------------------------------------------------------------------------------- /html/signaling.js: -------------------------------------------------------------------------------- 1 | /* 2 | Signaling 3 | --------- 4 | 5 | Connects to the signaling server, tries to find the room on the signaling server and 6 | receives the SDP for this room. 7 | 8 | 9 | 10 | 11 | sig.onjoin = function(room, sdp) { 12 | console.log(room, sdp); 13 | } 14 | 15 | sig.onconnect = function() { 16 | sig.join("party"); 17 | } 18 | 19 | sig.connect("ws://127.0.0.1:9001"); 20 | 21 | 22 | 23 | */ 24 | var Signaling = function() { 25 | 26 | var me = this; 27 | this.is_connected = false; /* used to keep state of our connection */ 28 | this.onjoin = null; /* gets called when you joined a room; SDP is given back. */ 29 | this.onconnect = null; /* gets called when connected. */ 30 | 31 | this.connect = function(url) { 32 | 33 | this.url = url; 34 | 35 | this.conn = new WebSocket(url); 36 | 37 | this.conn.onopen = function(ev) { 38 | me.is_connected = true 39 | 40 | if (me.onconnect) { 41 | me.onconnect(); 42 | } 43 | } 44 | 45 | this.conn.onclose = function(ev) { 46 | me.is_connected = false; 47 | } 48 | 49 | this.conn.onerror = function(ev) { 50 | console.error("onerror", ev); 51 | } 52 | 53 | this.conn.onmessage = function(ev) { 54 | 55 | var el = ev.data.split(' '); 56 | if (null != me.onjoin && el[0] == "sdp") { 57 | me.onjoin(el[1], el.slice(2, el.length).join(" ") ); 58 | } 59 | else { 60 | console.warn("Signaling - unhandled message."); 61 | } 62 | } 63 | } 64 | 65 | this.join = function(room) { 66 | 67 | if (!room) { 68 | return false; 69 | } 70 | 71 | if (!me.is_connected) { 72 | console.error("Not connected yet; cannot join."); 73 | return false; 74 | } 75 | 76 | this.conn.send("join " +room); 77 | } 78 | }; 79 | -------------------------------------------------------------------------------- /html/style.css: -------------------------------------------------------------------------------- 1 | 2 | * { 3 | font-family: Arial, sans-serif; 4 | font-family: 'Roboto', sans-serif; 5 | font-weight: 300; 6 | } 7 | 8 | body { 9 | background-color: whitesmoke; 10 | } 11 | 12 | button { 13 | background-color: #d84a38; 14 | border: none; 15 | border-radius: 2px; 16 | color: white; 17 | font-family: 'Roboto', sans-serif; 18 | font-size: 0.8em; 19 | margin: 0 0 1em 0; 20 | padding: 0.5em 0.7em 0.6em 0.7em; 21 | } 22 | 23 | button:active { 24 | background-color: #cf402f; 25 | } 26 | 27 | button:hover { 28 | background-color: #cf402f; 29 | } 30 | 31 | button[disabled] { 32 | color: #ccc; 33 | } 34 | 35 | button[disabled]:hover { 36 | background-color: #d84a38; 37 | } 38 | 39 | h1 { 40 | border-bottom: 1px solid #ccc; 41 | font-family: 'Roboto', sans-serif; 42 | font-weight: 500; 43 | margin: 0 0 0.8em 0; 44 | padding: 0 0 0.2em 0; 45 | } 46 | 47 | h2 { 48 | color: #444; 49 | font-size: 1em; 50 | font-weight: 500; 51 | line-height: 1.2em; 52 | margin: 0 0 0.8em 0; 53 | } 54 | 55 | h3 { 56 | border-top: 1px solid #eee; 57 | color: #666; 58 | font-size: 0.9em; 59 | font-weight: 500; 60 | margin: 20px 0 10px 0; 61 | padding: 10px 0 0 0; 62 | white-space: nowrap; 63 | } 64 | 65 | label { 66 | display: inline-block; 67 | } 68 | 69 | .form label { 70 | width: 100px; 71 | } 72 | 73 | input { 74 | border: 1px solid #ccc; 75 | padding: 5px; 76 | margin: 2px; 77 | } 78 | 79 | input.big { 80 | width: 400px; 81 | } 82 | 83 | /* ------------------------------ */ 84 | #container { 85 | margin: 0 auto 0 auto; 86 | max-width: 40em; 87 | padding: 1em 1.5em 1.3em 1.5em; 88 | } 89 | 90 | textarea { 91 | font-family:Courier, mono-space; 92 | font-size:10px; 93 | width: 100%; 94 | height:200px; 95 | margin-top:10px; 96 | border: 1px solid #ccc; 97 | padding: 5px; 98 | } 99 | 100 | #start_streaming { 101 | position:absolute; 102 | left:350px; 103 | top:440px; 104 | } 105 | 106 | #output_container { 107 | position:absolute; 108 | left:auto; 109 | right:0; 110 | } 111 | 112 | .video_container video { 113 | margin: 0 auto; 114 | display: block; 115 | background-color: #ccc; 116 | } 117 | 118 | .form_row { 119 | margin-bottom: 10px; 120 | } 121 | -------------------------------------------------------------------------------- /html/test_signaling.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebRTC 6 | 7 | 8 | 9 | 10 | 11 | 35 | 36 | 37 | 38 |
39 |

libwebrtc signaling example

40 | 41 |

42 |

43 |
44 | 45 | -------------------------------------------------------------------------------- /include/dtls/Context.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | dtls::Context 5 | ------------- 6 | 7 | Context for openSSL DTLS features. You can use this to craete a SSL_CTX and from 8 | that instantiate SSL* objects that can be used to encrypt/decrypt your data. This 9 | is created for the WebRTC DTLS part. This class allows you to automatically generate 10 | a certificate and key or load them from file. 11 | 12 | ** NOTE ** 13 | @todo - update dtls::Context.h info when we added support for passwords. 14 | ** NOTE ** 15 | 16 | Create server/client self-signed certificate/key (self signed, DONT ADD PASSWORD) 17 | -- 18 | openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout client-key.pem -out client-cert.pem 19 | openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -out server-cert.pem 20 | -- 21 | 22 | */ 23 | #ifndef DTLS_CONTEXT_H 24 | #define DTLS_CONTEXT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace dtls { 36 | 37 | class Context { 38 | public: 39 | Context(); 40 | ~Context(); 41 | bool init(); /* generates a certificate + private key on the fly */ 42 | bool init(std::string certfile, std::string keyfile); /* loads the given certificate + private key */ 43 | bool getFingerprint(std::string& result); /* returns the fingerprint for the certificate */ 44 | SSL* createSSL(); /* creates a new SSL* object with support with DTLS, giving ownership to the caller. */ 45 | 46 | private: 47 | bool createKey(); /* creates a EVP_PKEY that is used to store private keys */ 48 | bool createKeyAndCertificate(); /* creates a self signed certificate and private key */ 49 | bool createCertificate(); /* creates the X509 certificate using EVP_PKEY member */ 50 | bool createContext(); /* creates the SSL_CTX instance; only after the certificate and key have been created. */ 51 | bool loadPrivateKeyFile(std::string filepath); /* loads the private key from a file. */ 52 | bool loadCertificateFile(std::string filepath); /* loads the certificate from a file. */ 53 | 54 | public: 55 | X509* cert; /* the certificate */ 56 | EVP_PKEY* pkey; /* the private key. */ 57 | SSL_CTX* ctx; /* the SSL_CTX */ 58 | }; 59 | 60 | } /* namespace dtls */ 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /include/dtls/Parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | dtls::Parser 4 | ------------- 5 | Used to parse incoming DTLS data and keeps track of the current state 6 | of the SSL* member. It will call the `on_data()` callback whenever you need 7 | to send some data back to the end point for which you're using this parser. 8 | 9 | */ 10 | #ifndef DTLS_PARSER_H 11 | #define DTLS_PARSER_H 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #define DTLS_BUFFER_SIZE (1024 * 96) /* used to copy data from the mem bio */ 18 | 19 | /* SSL debug */ 20 | #define SSL_WHERE_INFO(ssl, w, flag, msg) { \ 21 | if(w & flag) { \ 22 | printf("----- "); \ 23 | printf("%20.20s", msg); \ 24 | printf(" - %30.30s ", SSL_state_string_long(ssl)); \ 25 | printf(" - %5.10s ", SSL_state_string(ssl)); \ 26 | printf("\n"); \ 27 | } \ 28 | } 29 | 30 | /* SRTP keying material sizes. */ 31 | #define DTLS_SRTP_MASTER_KEY_LEN 16 32 | #define DTLS_SRTP_MASTER_SALT_LEN 14 33 | #define DTLS_SRTP_MASTER_LEN (DTLS_SRTP_MASTER_KEY_LEN + DTLS_SRTP_MASTER_SALT_LEN) 34 | 35 | namespace dtls { 36 | 37 | typedef void (*dtls_parser_on_data_callback)(uint8_t* data, uint32_t nbytes, void* user); /* gets called when the parse has data ready that needs to be send back to the other party. */ 38 | 39 | enum ParserState { 40 | DTLS_STATE_NONE, 41 | }; 42 | 43 | enum ParserMode { 44 | DTLS_MODE_NONE, 45 | DTLS_MODE_CLIENT, 46 | DTLS_MODE_SERVER 47 | }; 48 | 49 | class Parser { 50 | public: 51 | Parser(); 52 | ~Parser(); 53 | bool init(); 54 | void process(uint8_t* data, uint32_t nbytes); /* process some encrypted data */ 55 | bool isHandshakeFinished(); 56 | bool extractKeyingMaterial(); /* only when the SSL handshake has finsihed, this will extract the keying material that is used by srtp. */ 57 | const char* getCipherSuite(); /* returns the selected cipher suite, of < 0 on error. we set the given suite parameter to the one that we use. */ 58 | 59 | private: 60 | void checkOutputBuffer(); /* checks is there is data in our out_bio and that we need to send something to the other party. */ 61 | 62 | public: 63 | SSL* ssl; /* the SSL object that tracks state. must be set by user, we take ownership and free it in the d'tor. */ 64 | BIO* in_bio; /* we use memory read bios. */ 65 | BIO* out_bio; /* we use memory write bios. */ 66 | ParserState state;/* @todo - check if we can't use the ssl member to tack state. */ /* used to state and makes sure the on_data callback is called at the right time. */ 67 | ParserMode mode; /* is this a client or server implementation */ 68 | uint8_t* buffer; /* is used to copy data out our out_bio/in_bio */ 69 | dtls_parser_on_data_callback on_data; /* is called when there is data that needs to be send to the other party */ 70 | void* user; /* gets passed into the callbacks */ 71 | uint8_t keying_material[DTLS_SRTP_MASTER_LEN * 2]; /* contains the keying material. */ 72 | uint8_t* remote_key; /* remote key, used by srtp, points into keying_material */ 73 | uint8_t* remote_salt; /* remote salt, used by srtp, points into keying_material */ 74 | uint8_t* local_key; /* local key, used by srtp, points into keying_material */ 75 | uint8_t* local_salt; /* local salt, used by srtp, points into keying_material */ 76 | }; 77 | 78 | } /* namespace dtls */ 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/ice/Agent.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Agent 4 | ----- 5 | 6 | This is an experimental class to keep track of the state of an agent 7 | and it's candidates. We only support ICE-LITE atm. 8 | 9 | Should be used with a (server) sdp, with a=ice-lite, e.g: 10 | 11 | 12 | v=0 13 | o=- 5372151867866539221 2 IN IP4 127.0.0.1 14 | s=- 15 | t=0 0 16 | a=ice-lite 17 | m=video 1 RTP/SAVPF 100 18 | c=IN IP4 192.168.0.193 19 | a=mid:video 20 | a=recvonly 21 | a=rtcp-mux 22 | a=rtpmap:100 VP8/90000 23 | a=ice-ufrag:5PN2qmWqBl 24 | a=ice-pwd:Q9wQj99nsQzldVI5ZuGXbEWRK5RhRXdC 25 | a=candidate:4252876256 1 udp 2122260223 192.168.0.193 59976 typ host 26 | a=candidate:4252876256 2 udp 2122260223 192.168.0.193 59976 typ host 27 | a=fingerprint:sha-256 3C:A8:D2:9B:34:9C:F1:94:F5:FD:AD:61:1D:79:21:4D:75:32:23:BB:ED:2E:85:02:79:C9:80:1D:A8:BB:A9:8A 28 | a=setup:passive 29 | 30 | 31 | 32 | References: 33 | ----------- 34 | - Agent states: http://docs.webplatform.org/wiki/apis/webrtc/RTCPeerConnection/iceState 35 | 36 | */ 37 | 38 | #ifndef ICE_AGENT_H 39 | #define ICE_AGENT_H 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | namespace ice { 49 | 50 | class Agent { 51 | public: 52 | Agent(); 53 | ~Agent(); 54 | bool init(); /* After adding streams (and candidates to streams), call init to kick off everythign */ 55 | void update(); /* This must be called often as it fetches new data from the socket and parses any incoming data */ 56 | void addStream(Stream* stream); /* Add a new stream, this class takes ownership */ 57 | void setCredentials(std::string ufrag, std::string pwd); /* set the credentials (ice-ufrag, ice-pwd) for all streams. */ 58 | void handleStunMessage(Stream* stream, stun::Message* msg, std::string rip, uint16_t rport, std::string lip, uint16_t lport); /* Handles incoming stun messages for the given stream and candidates. It will make sure the correct action will be taken. */ 59 | void handleStreamData(Stream* stream, std::string rip, uint16_t rport, std::string lip, uint16_t lport, uint8_t* data, uint32_t nbytes) ; 60 | std::string getSDP(); /* Experimental: based on the added streams / candidates, this will return an SDP that can be shared the other agents. */ 61 | 62 | public: 63 | std::vector streams; 64 | dtls::Context dtls_ctx; /* The dtls::Context is used to handle the dtls communication */ 65 | stun::Reader stun; /* Used to parse incoming data and detect stun messages */ 66 | bool is_lite; /* At this moment we only support ice-lite. */ 67 | }; 68 | } /* namespace ice */ 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /include/ice/Candidate.h: -------------------------------------------------------------------------------- 1 | #ifndef ICE_CANDIDATE_H 2 | #define ICE_CANDIDATE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace ice { 12 | 13 | /* -------------------------------------------------- */ 14 | 15 | class Candidate { 16 | public: 17 | Candidate(std::string ip, uint16_t port); 18 | bool init(connection_on_data_callback cb, void* user); /* pass in the function which will receive the data from the socket. */ 19 | void update(); /* read data from the socket + process */ 20 | 21 | public: 22 | std::string ip; /* the ip to which we can send data */ 23 | uint16_t port; /* the port to which we can send data */ 24 | uint8_t component_id; /* compoment id */ 25 | rtc::ConnectionUDP conn; /* the (udp for now) connection on which we receive data; later we can decouple this if necessary. */ 26 | connection_on_data_callback on_data; /* will be called whenever we receive data from the socket. */ 27 | void* user; /* user data */ 28 | 29 | /* only local candidates initialize these contexts */ 30 | dtls::Parser dtls; /* a local candidate sets up dtls context */ 31 | srtp::ParserSRTP srtp_out; /* used to protect outgoing data. */ 32 | srtp::ParserSRTP srtp_in; /* used to unprotect incoming data. */ 33 | }; 34 | 35 | /* -------------------------------------------------- */ 36 | 37 | class CandidatePair { 38 | public: 39 | CandidatePair(); 40 | CandidatePair(Candidate* local, Candidate* remote); 41 | ~CandidatePair(); 42 | 43 | public: 44 | Candidate* local; /* local candidate; which has a socket (ConnectionUDP) */ 45 | Candidate* remote; /* the remote party from which we receive data and send data towards. */ 46 | }; 47 | 48 | } /* namespace ice */ 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/ice/Stream.h: -------------------------------------------------------------------------------- 1 | #ifndef ICE_STREAM_H 2 | #define ICE_STREAM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* flags, used to control the way the stream works */ 10 | #define STREAM_FLAG_NONE 0x0000 11 | #define STREAM_FLAG_VP8 0x0001 12 | #define STREAM_FLAG_RTCP_MUX 0x0002 13 | #define STREAM_FLAG_SENDRECV 0x0004 14 | #define STREAM_FLAG_RECVONLY 0x0008 15 | 16 | namespace ice { 17 | 18 | class Stream; 19 | 20 | /* gets called when a stream received data, for which we haven't found a candidate pair yet. */ 21 | typedef void(*stream_data_callback)(Stream* stream, 22 | std::string rip, uint16_t rport, 23 | std::string lip, uint16_t lport, 24 | uint8_t* data, uint32_t nbytes, void* user); 25 | 26 | /* gets called when we have MEDIA data from a valid candidate (RTP, DTLS, RTCP), e.g. similar to stream_data_callback, only we have a valid candidate pair now. */ 27 | typedef void(*stream_media_callback)(Stream* stream, CandidatePair* pair, 28 | uint8_t* data, uint32_t nbytes, void* user); 29 | 30 | 31 | class Stream { 32 | public: 33 | Stream(uint32_t flags = STREAM_FLAG_NONE); 34 | ~Stream(); 35 | bool init(); /* initialize, must be called once after all local candidates have been added */ 36 | void update(); /* must be called often, which flush any pending buffers */ 37 | void addLocalCandidate(Candidate* c); /* add a candidate; we take ownership of the candidate and free it in the d'tor. */ 38 | void addRemoteCandidate(Candidate* c); /* add a remote candidate; is done whenever we recieve data from a ip:port for which no CandidatePair exists. */ 39 | void addCandidatePair(CandidatePair* p); /* add a candidate pair; local -> remote data flow */ 40 | void setCredentials(std::string ufrag, std::string pwd); /* set the credentials (ice-ufrag, ice-pwd) for all candidates. */ 41 | CandidatePair* createPair(std::string rip, uint16_t rport, std::string lip, uint16_t lport);/* creates a new candidate pair for the given IPs, ofc. when the local stream exists */ 42 | CandidatePair* findPair(std::string rip, uint16_t rport, std::string lip, uint16_t lport); /* used internally to find a pair on which data flows */ 43 | Candidate* findLocalCandidate(std::string ip, uint16_t port); /* find a local candidate for the given local ip and port. */ 44 | Candidate* findRemoteCandidate(std::string ip, uint16_t port); /* find a remote candidate for the given remote ip and port. */ 45 | int sendRTP(uint8_t* data, uint32_t nbytes); /* send unprotected RTP data; we will make sure it's protected. */ 46 | 47 | public: 48 | std::vector local_candidates; /* our local candidates */ 49 | std::vector remote_candidates; /* our remote candidates */ 50 | std::vector pairs; /* the candidate pairs */ 51 | stream_data_callback on_data; /* the stream data callback; is called whenever one of the transports receives data; the Agent handles incoming data. */ 52 | stream_media_callback on_rtp; /* is called whenever there is decoded rtp data; it's up to the user to call this at the right time, e.g. see Agent.cpp */ 53 | void* user_data; /* user data that is passed to the on_data handler. */ 54 | void* user_rtp; /* user data that is passed to the on_rtp handler. */ 55 | std::string ice_ufrag; /* the ice_ufrag from the sdp */ 56 | std::string ice_pwd; /* the ice-pwd value from the sdp, used when adding the message-integrity element to the responses. */ 57 | uint32_t flags; /* bitflags, defines the featues of the stream; e.g. is it VP8, does it use RTCP-MUX, etc.. */ 58 | }; 59 | 60 | } /* namespace ice */ 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /include/ice/Utils.h: -------------------------------------------------------------------------------- 1 | #ifndef ICE_UTILS_H 2 | #define ICE_UTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace ice { 9 | 10 | std::string gen_random_string(const int len); /* generates a random alpha-num string with the given len. */ 11 | std::vector get_interface_addresses(); /* retrieve interface addresses, can be used to create a SDP.*/ 12 | 13 | } /* namespace ice */ 14 | #endif 15 | -------------------------------------------------------------------------------- /include/rtc/Connection.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Connection 4 | ----------- 5 | This code is still experimental and the API will/may change. At this 6 | moment I'm not sure how to abstract the network I/O (udp/tcp) and the 7 | coupling with DTLS. 8 | 9 | At this moment there is a base Connection and an ConnectionUDP class. 10 | 11 | */ 12 | #ifndef RTC_CONNECTION_H 13 | #define RTC_CONNECTION_H 14 | 15 | extern "C" { 16 | # include 17 | } 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | typedef void(*connection_on_data_callback)(std::string rip, uint16_t rport, /* local ip and port */ 24 | std::string lip, uint16_t lport, /* remote ip and port */ 25 | uint8_t* data, uint32_t nbytes, void* user); /* gets called when a connection receives some data. */ 26 | 27 | namespace rtc { 28 | 29 | class Connnection { 30 | }; 31 | 32 | class ConnectionUDP { 33 | 34 | public: 35 | ConnectionUDP(); 36 | bool bind(std::string ip, uint16_t port); 37 | void update(); 38 | // void send(uint8_t* data, uint32_t nbytes); /* @todo - deprecated, use sendTo */ 39 | void sendTo(std::string rip, uint16_t rport, uint8_t* data, uint32_t nbytes); 40 | public: 41 | std::string ip; 42 | uint16_t port; 43 | struct sockaddr_in raddr; /* receive */ 44 | // struct sockaddr* saddr; /* send (will not be necessary anymore! @todo remove when ice things are working) */ 45 | uv_udp_t sock; 46 | uv_loop_t* loop; 47 | 48 | /* callbacks */ 49 | connection_on_data_callback on_data; 50 | void* user; 51 | }; 52 | 53 | } /* namespace rtc */ 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /include/rtp/PacketVP8.h: -------------------------------------------------------------------------------- 1 | #ifndef RTP_PACKET_VP8_H 2 | #define RTP_PACKET_VP8_H 3 | 4 | #include 5 | 6 | namespace rtp { 7 | 8 | class PacketVP8 { 9 | public: 10 | PacketVP8(); 11 | ~PacketVP8(); 12 | void reset(); 13 | 14 | public: 15 | 16 | /* rtp header */ 17 | uint8_t version; 18 | uint8_t padding; 19 | uint8_t extension; 20 | uint8_t csrc_count; 21 | uint8_t marker; /* set for the very last packet of each encoded frame in line with the normal use of the M bit in video formats. For VP8 this will be set to 1 when the last packet for a frame is received. */ 22 | uint8_t payload_type; 23 | uint16_t sequence_number; 24 | uint32_t timestamp; 25 | uint32_t ssrc; 26 | 27 | /* required */ 28 | uint8_t X; /* extended controlbits present */ 29 | uint8_t N; /* (non-reference frame) when set to 1 this frame can be discarded */ 30 | uint8_t S; /* start of VP8 partition */ 31 | uint8_t PID; /* partition index */ 32 | 33 | /* 2nd second row Payload Descriptor (is optional) */ 34 | uint8_t I; /* 1 if PictureID is present */ 35 | uint8_t L; /* 1 if TL0PICIDX is present */ 36 | uint8_t T; /* 1 if TID is present */ 37 | uint8_t K; /* 1 if KEYIDX is present */ 38 | uint16_t PictureID; /* 8 or 16 bits, picture ID */ 39 | uint8_t TL0PICIDX; /* 8 bits temporal level zero index */ 40 | 41 | /* 3rd row Payload Descriptor */ 42 | uint8_t M; /* Extension flag; must be present if I bit == 1. If set, the PictureID field must contains 16 bits, else 8*/ 43 | 44 | /* payload header */ 45 | uint8_t P; /* 0 if current frame is a key frame, otherwise 1 */ 46 | 47 | /* the actual frame/partition data */ 48 | uint8_t* payload; /* points to the start of the partition data that can be fed into the decoder (once a frame has been constructed.). We do not copy the data! */ 49 | uint32_t nbytes; /* number of bytes in the partition */ 50 | }; 51 | 52 | } /* namespace rtp */ 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /include/rtp/ReaderVP8.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | RTP VP8 extension (writer) 4 | -------------------------- 5 | 6 | See: 7 | - RFC: http://tools.ietf.org/html/draft-ietf-payload-vp8-11#section-4.2 8 | - Example code: https://gist.github.com/roxlu/df0a786a8bf81e75ef0e 9 | 10 | */ 11 | #ifndef RTP_READER_VP8 12 | #define RTP_READER_VP8 13 | 14 | #include 15 | #include 16 | 17 | namespace rtp { 18 | 19 | int rtp_vp8_decode(uint8_t* data, uint32_t nbytes, PacketVP8* pkt); 20 | 21 | } /* namespace rtp */ 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/rtp/WriterVP8.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | RTP VP8 extension (writer) 4 | -------------------------- 5 | 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace rtp { 15 | 16 | typedef void(*rtp_vp8_on_packet)(PacketVP8* pkt, void* user); /* gets called whenever a new RTP-VP8 packet is created; one vpx_codec_cx_pkt_t can result in multiple RTP-VP8 packets. */ 17 | 18 | class WriterVP8 { 19 | 20 | public: 21 | WriterVP8(); 22 | ~WriterVP8(); 23 | int packetize(const vpx_codec_cx_pkt_t* pkt); /* create a RTP-VP8 packet. */ 24 | 25 | public: 26 | uint32_t ssrc; /* RTP ssrc */ 27 | uint16_t seqnum; /* RTP sequence number, starts with a random value. */ 28 | uint16_t picture_id; /* RTP-VP8 picture id, starts with a random value. */ 29 | rtp_vp8_on_packet on_packet; /* must be set by user; will receive a RTP packet. */ 30 | void* user; /* gets passed into the callback */ 31 | 32 | private: 33 | uint32_t capacity; /* the capacity of our buffer */ 34 | uint8_t* buffer; /* the buffer that will hold the VP8 data. */ 35 | }; 36 | 37 | 38 | } /* namespace rtp */ 39 | -------------------------------------------------------------------------------- /include/sdp/Reader.h: -------------------------------------------------------------------------------- 1 | #ifndef SDP_READER_H 2 | #define SDP_READER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace sdp { 12 | 13 | /* our parse exception */ 14 | struct ParseException : public std::exception { 15 | std::string s; 16 | ParseException(std::string s):s(s) {} 17 | ~ParseException() throw() {} 18 | const char* what() const throw() { return s.c_str(); }; 19 | }; 20 | 21 | /* one element of a Line */ 22 | class Token { 23 | public: 24 | Token(); 25 | Token(std::string value); 26 | bool isNumeric(); 27 | size_t size(); 28 | 29 | /* conversion functions */ 30 | int toInt(); 31 | uint64_t toU64(); 32 | std::string toString(); 33 | AddrType toAddrType(); 34 | NetType toNetType(); 35 | MediaType toMediaType(); 36 | MediaProto toMediaProto(); 37 | CandType toCandType(); 38 | SetupType toSetupType(); 39 | 40 | public: 41 | std::string value; 42 | }; 43 | 44 | /* a sdp line, e.g "a=rtcp:59976 IN IP4 192.168.0.194" */ 45 | class Line { 46 | public: 47 | Line(); 48 | Line(std::string src); 49 | 50 | /* generic parse functions */ 51 | void skip(char until); /* skip some characters until you find the given character. */ 52 | void ltrim(); /* trim whitespace from left from current index. */ 53 | Token getToken(char until = ' '); /* read part of a sdp line until the given character. */ 54 | char operator[](unsigned int); 55 | 56 | /* read the next token as a specific type */ 57 | bool readType(char type); /* read until the type element (e.g. o=, v=, a=) and return true when the line is the given type. */ 58 | std::string readString(char until = ' '); /* read a string from the next token */ 59 | int readInt(char until = ' '); /* read an integer value from the next token */ 60 | uint64_t readU64(char until = ' '); /* read an integer (u64). */ 61 | AddrType readAddrType(char until = ' '); /* read an AddrType */ 62 | NetType readNetType(char until = ' '); /* read a NetType */ 63 | MediaType readMediaType(char until = ' '); /* read a MediaType */ 64 | MediaProto readMediaProto(char until = ' '); /* read a MediaProto */ 65 | CandType readCandType(char until = ' '); /* read a CandType */ 66 | SetupType readSetupType(char until = ' '); /* read a SetupType */ 67 | 68 | public: 69 | std::string value; 70 | size_t index; /* used to keep track until which character one has read. */ 71 | }; 72 | 73 | /* parses an SDP */ 74 | class Reader { 75 | public: 76 | int parse(std::string source, SDP* result); 77 | 78 | private: 79 | Node* parseLine(Line& line); 80 | Version* parseVersion(Line& line); /* v= */ 81 | Origin* parseOrigin(Line& line); /* o= */ 82 | SessionName* parseSessionName(Line& line); /* s= */ 83 | SessionInformation* parseSessionInformation(Line& line); /* i= */ 84 | URI* parseURI(Line& line); /* u= */ 85 | EmailAddress* parseEmailAddress(Line& line); /* e= */ 86 | PhoneNumber* parsePhoneNumber(Line& line); /* p= */ 87 | ConnectionData* parseConnectionData(Line& line); /* c= */ 88 | Timing* parseTiming(Line& line); /* t= */ 89 | Media* parseMedia(Line& line); /* m= */ 90 | Attribute* parseAttribute(Line& line); /* a= */ 91 | }; 92 | 93 | } 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /include/sdp/SDP.h: -------------------------------------------------------------------------------- 1 | #ifndef SDP_H 2 | #define SDP_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace sdp { 9 | 10 | class SDP : public Node { 11 | public: 12 | SDP(); 13 | 14 | }; 15 | 16 | 17 | } /* namespace sdp */ 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/sdp/Types.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Types 4 | ----- 5 | 6 | This file contains the structs/nodes that make up a SDP and is based on RFC4566. 7 | We follow the same naming as the elements as described in RFC4566. 8 | We implement the nodes in the same order as described in the "SDP specification" 9 | chapter in http://tools.ietf.org/html/rfc4566.html 10 | 11 | */ 12 | 13 | #ifndef SDP_TYPES_H 14 | #define SDP_TYPES_H 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | namespace sdp { 21 | 22 | enum Type { 23 | SDP_NONE, 24 | SDP_SESSION, /* a full SDP session */ 25 | SDP_ORIGIN, 26 | SDP_VERSION, 27 | SDP_SESSION_NAME, 28 | SDP_SESSION_INFORMATION, 29 | SDP_URI, 30 | SDP_EMAIL_ADDRESS, 31 | SDP_PHONE_NUMBER, 32 | SDP_CONNECTION_DATA, 33 | SDP_TIMING, 34 | SDP_MEDIA, 35 | SDP_CANDIDATE, 36 | SDP_ATTRIBUTE 37 | }; 38 | 39 | enum NetType { 40 | SDP_NETTYPE_NONE, 41 | SDP_IN 42 | }; 43 | 44 | enum AddrType { 45 | SDP_ADDRTYPE_NONE, 46 | SDP_IP4, 47 | SDP_IP6 48 | }; 49 | 50 | enum MediaType { 51 | SDP_MEDIATYPE_NONE, 52 | SDP_VIDEO, 53 | SDP_AUDIO, 54 | SDP_TEXT, 55 | SDP_APPLICATION, 56 | SDP_MESSAGE 57 | }; 58 | 59 | enum MediaProto { 60 | SDP_MEDIAPROTO_NONE, 61 | SDP_UDP, 62 | SDP_RTP_AVP, 63 | SDP_RTP_SAVP, 64 | SDP_RTP_SAVPF /* http://tools.ietf.org/html/rfc5124 */ 65 | }; 66 | 67 | enum AttrType { 68 | SDP_ATTRTYPE_NONE, 69 | SDP_ATTR_RTCP, 70 | SDP_ATTR_KEYWDS, 71 | SDP_ATTR_TOOL, 72 | SDP_ATTR_PTIME, 73 | SDP_ATTR_MAXPTIME, 74 | SDP_ATTR_RTPMAP, 75 | SDP_ATTR_RECVONLY, 76 | SDP_ATTR_SENDRECV, 77 | SDP_ATTR_SENDONLY, 78 | SDP_ATTR_INACTIVE, 79 | SDP_ATTR_ORIENT, 80 | SDP_ATTR_TYPE, 81 | SDP_ATTR_CHARSET, 82 | SDP_ATTR_SDPLANG, 83 | SDP_ATTR_LANG, 84 | SDP_ATTR_CANDIDATE, 85 | SDP_ATTR_ICE_UFRAG, 86 | SDP_ATTR_ICE_PWD, 87 | SDP_ATTR_ICE_OPTIONS, 88 | SDP_ATTR_FINGERPRINT, 89 | SDP_ATTR_SETUP, 90 | 91 | /* etc... etc.. */ 92 | SDP_ATTR_UNKNOWN /* an generic attribute. different from SDP_ATTRTYPE_NONE as this one has been explicitly set by the user */ 93 | }; 94 | 95 | /* a=candidate: */ 96 | enum CandType { 97 | SDP_CANDTYPE_NONE, 98 | SDP_HOST, 99 | SDP_SRFLX, 100 | SDP_PRFLX, 101 | SDP_RELAY 102 | }; 103 | 104 | /* a=setup: */ 105 | enum SetupType { 106 | SDP_SETUPTYPE_NONE, 107 | SDP_ACTIVE, 108 | SDP_PASSIVE, 109 | SDP_ACTPASS, 110 | SDP_HOLDCONN 111 | }; 112 | 113 | /* forward declared for Node::find() */ 114 | struct Version; 115 | struct Origin; 116 | struct SessionName; 117 | struct SessionInformation; 118 | struct Timing; 119 | struct ConnectionData; 120 | struct Media; 121 | struct Attribute; 122 | struct AttributeRTCP; 123 | struct AttributeCandidate; 124 | 125 | struct Node { 126 | public: 127 | Node(Type t); 128 | virtual ~Node(); 129 | void add(Node* n); 130 | bool find(Type t, std::vector& result); /* will try to find a child node for the given type */ 131 | bool find(MediaType t, Media** result); /* will set result to the first found media element of the given media type. */ 132 | bool find(AttrType t, Attribute** result); /* will set result to the first occurence of the attribute type. */ 133 | bool find(AttrType t, std::vector& result); /* find all attributes for the given type. */ 134 | void remove(Type t); /* remove all nodes of the given type. */ 135 | void remove(AttrType t); /* remove attributes of this type. */ 136 | 137 | public: 138 | Type type; 139 | std::vector nodes; 140 | }; 141 | 142 | /* v= */ 143 | struct Version : public Node { 144 | Version(); 145 | int version; 146 | }; 147 | 148 | /* o= */ 149 | struct Origin : public Node { 150 | Origin(); 151 | 152 | std::string username; /* users login, or "-" if you dont support user ids. */ 153 | std::string sess_id; /* numeric string that is used as unique identifier, e.g. timestamp, e.g. "621762799816690644" */ 154 | uint64_t sess_version; /* version number of this SDP, e.g. "1" */ 155 | NetType net_type; /* SDP_IN */ 156 | AddrType addr_type; /* SDP_IP4, SDP_IP6 */ 157 | std::string unicast_address; /* address of the machine from which the session was created, e.g. 127.0.0.1 */ 158 | }; 159 | 160 | /* s= */ 161 | struct SessionName : public Node { 162 | SessionName(); 163 | std::string session_name; 164 | }; 165 | 166 | /* i= */ 167 | struct SessionInformation : public Node { 168 | SessionInformation(); 169 | std::string session_description; 170 | }; 171 | 172 | /* u= */ 173 | struct URI : public Node { 174 | URI(); 175 | std::string uri; 176 | }; 177 | 178 | /* e= */ 179 | struct EmailAddress : public Node { 180 | EmailAddress(); 181 | std::string email_address; 182 | }; 183 | 184 | /* p= */ 185 | struct PhoneNumber : public Node { 186 | PhoneNumber(); 187 | std::string phone_number; 188 | }; 189 | 190 | /* t= */ 191 | struct Timing : public Node { 192 | Timing(); 193 | uint64_t start_time; 194 | uint64_t stop_time; 195 | }; 196 | 197 | /* c= */ 198 | struct ConnectionData : public Node { 199 | ConnectionData(); 200 | NetType net_type; 201 | AddrType addr_type; 202 | std::string connection_address; 203 | }; 204 | 205 | /* m= */ 206 | struct Media : public Node { 207 | Media(); 208 | MediaType media; 209 | uint16_t port; 210 | MediaProto proto; 211 | int fmt; 212 | }; 213 | 214 | /* 215 | 216 | Because the list of attribute types is huge, we create a generic Attribute 217 | struct which contains some members that are meant for common types. So in general 218 | not all members of this sturct are always used. The reader will set the members 219 | base on the AttrType member. 220 | 221 | a= 222 | */ 223 | struct Attribute : public Node { 224 | Attribute(); 225 | Attribute(std::string name, std::string value, AttrType atype = SDP_ATTR_UNKNOWN); 226 | AttrType attr_type; 227 | std::string name; 228 | std::string value; 229 | }; 230 | 231 | /* a=rtcp:59976 IN IP4 192.168.0.194 */ 232 | struct AttributeRTCP : public Attribute { 233 | AttributeRTCP(); 234 | uint16_t port; 235 | NetType net_type; 236 | AddrType addr_type; 237 | std::string connection_address; 238 | }; 239 | 240 | /* a=candidate:4252876256 1 udp 2122260223 192.168.0.194 59976 typ host generation 0 */ 241 | struct AttributeCandidate : public Attribute { 242 | AttributeCandidate(); 243 | 244 | std::string foundation; 245 | uint64_t component_id; 246 | std::string transport; 247 | uint64_t priority; 248 | std::string connection_address; 249 | int port; 250 | CandType cand_type; 251 | std::string rel_addr; 252 | uint16_t rel_port; 253 | }; 254 | 255 | /* a=fingerprint:sha-256 EA:A3:3E:F1:7F:36:62:AA:AE:31:ED:9E:B5:B6:FA:CE:56:8A:29:4C:A3:C5:F7:28:3D:1B:72:5A:68:9F:FE:33 */ 256 | /* see: http://www.rfc-editor.org/rfc/rfc4572.txt, section 5 */ 257 | struct AttributeFingerprint : public Attribute { 258 | AttributeFingerprint(); 259 | AttributeFingerprint(std::string hfunc, std::string fprint); 260 | 261 | std::string hash_func; 262 | std::string fingerprint; 263 | }; 264 | 265 | /* a=setup: ... */ 266 | struct AttributeSetup : public Attribute { 267 | AttributeSetup(); 268 | AttributeSetup(SetupType role); 269 | void makeActive(); 270 | void makePassive(); 271 | SetupType role; 272 | }; 273 | 274 | }; 275 | 276 | #endif 277 | -------------------------------------------------------------------------------- /include/sdp/Utils.h: -------------------------------------------------------------------------------- 1 | #ifndef SDP_UTILS_H 2 | #define SDP_UTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace sdp { 13 | 14 | bool string_to_net_type(std::string& input, NetType& result); /* convert a string to a NetType */ 15 | bool string_to_addr_type(std::string& input, AddrType& result); /* convert a string to an AddrType */ 16 | bool string_to_media_type(std::string& input, MediaType& result); /* convert a string to a MediaType */ 17 | bool string_to_media_proto(std::string& input, MediaProto& result); /* convert a string to a MediaType */ 18 | bool string_to_cand_type(std::string& input, CandType& result); /* convert a string to a CandType */ 19 | bool string_to_setup_type(std::string& input, SetupType& result); /* convert a string to a SetupType for the a=setup: attribute */ 20 | std::string net_type_to_string(NetType type); 21 | std::string addr_type_to_string(AddrType type); 22 | std::string media_type_to_string(MediaType type); 23 | std::string media_proto_to_string(MediaProto proto); 24 | std::string cand_type_to_string(CandType type); 25 | std::string setup_type_to_string(SetupType type); 26 | 27 | 28 | /* trim from right */ 29 | inline static std::string rtrim(const std::string &source , const std::string& t = " " ) { 30 | std::string str = source; 31 | return str.erase (str.find_last_not_of(t) + 1); 32 | } 33 | 34 | /* trim from left */ 35 | inline static std::string ltrim(const std::string& source, const std::string& t = " ") { 36 | std::string str = source; 37 | return str.erase (0 , source.find_first_not_of(t)); 38 | } 39 | 40 | /* trim from both left and right */ 41 | inline static std::string trim ( const std::string& source, const std::string& t = " ") { 42 | std::string str = source; 43 | return ltrim(rtrim (str, t) , t); 44 | } 45 | 46 | /* tokenizes the input on the given character. */ 47 | inline int tokenize(std::string input, char delim, std::vector& output) { 48 | 49 | std::stringstream ss(input); 50 | std::string line; 51 | 52 | while (std::getline(ss, line, delim)) { 53 | output.push_back(line); 54 | } 55 | 56 | if (!output.size()) { 57 | return -1; 58 | } 59 | 60 | return 0; 61 | 62 | }; 63 | 64 | /* check if the given value is numeric */ 65 | inline bool is_numeric(std::string s) { 66 | std::string::const_iterator it = s.begin(); 67 | while (it != s.end() && std::isdigit(*it)) { 68 | ++it; 69 | } 70 | return !s.empty() && it == s.end(); 71 | } 72 | 73 | /* converts the given string to another type */ 74 | template T convert(std::string value) { 75 | T result; 76 | std::stringstream ss(value); 77 | ss >> result; 78 | return result; 79 | } 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /include/sdp/Writer.h: -------------------------------------------------------------------------------- 1 | #ifndef SDP_WRITER_H 2 | #define SDP_WRITER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace sdp { 12 | 13 | class Writer { 14 | public: 15 | std::string toString(SDP* sdp); 16 | std::string toString(Node* sdp); 17 | std::string toString(Version* v); 18 | std::string toString(Origin* o); 19 | std::string toString(SessionName* s); 20 | std::string toString(Timing* t); 21 | std::string toString(Media* m); 22 | std::string toString(Attribute* a); 23 | std::string toString(AttributeCandidate* c); 24 | std::string toString(AttributeFingerprint* f); 25 | std::string toString(AttributeSetup* f); 26 | }; 27 | 28 | } /* namesapce sdp */ 29 | #endif 30 | -------------------------------------------------------------------------------- /include/signaling/Room.h: -------------------------------------------------------------------------------- 1 | #ifndef WEBRTC_SIGNALING_ROOM_H 2 | #define WEBRTC_SIGNALING_ROOM_H 3 | 4 | #include 5 | 6 | namespace sig { 7 | 8 | class Room { 9 | public: 10 | Room(std::string name, std::string sdp); 11 | 12 | public: 13 | std::string name; 14 | std::string sdp; 15 | }; 16 | 17 | 18 | } /* namespace sig */ 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/signaling/Signaling.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Signaling 4 | --------- 5 | 6 | Experimental and basic implementation of a signaling websocket API. We're 7 | starting this signal server with the idea that it will be embedded in a 8 | custom application which wants to allow users to connect to it using WebRTC. 9 | 10 | The signaling server uses 'rooms' keep state. Each room has things like 11 | the SDP of the server, name, etc. 12 | 13 | */ 14 | #ifndef WEBRTC_SIGNALING_H 15 | #define WEBRTC_SIGNALING_H 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace sig { 24 | 25 | class Signaling { 26 | 27 | public: 28 | Signaling(); 29 | ~Signaling(); 30 | int init(SignalingSettings cfg); 31 | int addRoom(Room* room); 32 | int start(); 33 | int stop(); 34 | 35 | Room* findRoom(std::string name); 36 | 37 | /* API */ 38 | void handleJoin(struct mg_connection* conn); 39 | 40 | public: 41 | SignalingSettings settings; 42 | std::vector rooms; 43 | struct mg_server* server; 44 | bool must_stop; 45 | }; 46 | 47 | } /* namespace sig */ 48 | #endif 49 | -------------------------------------------------------------------------------- /include/signaling/SignalingSettings.h: -------------------------------------------------------------------------------- 1 | #ifndef WEBRTC_SIGNALING_SETTINGS_H 2 | #define WEBRTC_SIGNALING_SETTINGS_H 3 | 4 | #include 5 | 6 | namespace sig { 7 | 8 | class SignalingSettings { 9 | public: 10 | SignalingSettings(); 11 | ~SignalingSettings(); 12 | 13 | public: 14 | std::string port; 15 | }; 16 | 17 | } /* namespace sig */ 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/srtp/ParserSRTP.h: -------------------------------------------------------------------------------- 1 | #ifndef SRTP_PARSER_H 2 | #define SRTP_PARSER_H 3 | 4 | #include 5 | #include 6 | 7 | #define SRTP_PARSER_MASTER_KEY_LEN 16 8 | #define SRTP_PARSER_MASTER_SALT_LEN 14 9 | #define SRTP_PARSER_MASTER_LEN (SRTP_PARSER_MASTER_KEY_LEN + SRTP_PARSER_MASTER_SALT_LEN) 10 | 11 | 12 | namespace srtp { 13 | 14 | class ParserSRTP { 15 | 16 | public: 17 | ParserSRTP(); 18 | ~ParserSRTP(); 19 | int init(const char* cipher, bool inbound, const uint8_t* key, const uint8_t* salt); 20 | int protectRTP(void* in, uint32_t nbytes); 21 | int protectRTCP(void* in, uint32_t nbytes); 22 | int unprotectRTP(void* in, uint32_t nbytes); 23 | int unprotectRTCP(void* in, uint32_t nbytes); 24 | 25 | public: 26 | static bool is_lib_init; 27 | bool is_init; 28 | srtp_t session; 29 | srtp_policy_t policy; 30 | }; 31 | 32 | } /* namespace srtp */ 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/stun/Attribute.h: -------------------------------------------------------------------------------- 1 | #ifndef STUN_ATTRIBUTE_H 2 | #define STUN_ATTRIBUTE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace stun { 10 | 11 | /* --------------------------------------------------------------------- */ 12 | 13 | class Attribute { 14 | public: 15 | Attribute(uint16_t type = STUN_ATTR_TYPE_NONE); 16 | 17 | public: 18 | uint16_t type; 19 | uint16_t length; /* The number of bytes of the attribute data. This is the size w/o the padded bytes that are added when the the attribute is not padded to 32 bits. */ 20 | uint16_t nbytes; /* The number of bytes the attribute takes inside the buffer. Because the STUN message has to be padded on 32 bits the length may be different from the nbytes. Also, this nbytes includes the bytes of the type field and length field. */ 21 | uint32_t offset; /* Byte offset where the header of the attribute starts in the Message::buffer. */ 22 | }; 23 | 24 | /* --------------------------------------------------------------------- */ 25 | 26 | class StringValue { 27 | public: 28 | StringValue(){} 29 | StringValue(std::string v) { std::copy(v.begin(), v.end(), std::back_inserter(buffer)); } 30 | std::vector buffer; 31 | }; 32 | 33 | /* --------------------------------------------------------------------- */ 34 | 35 | class Username : public Attribute { 36 | public: 37 | Username():Attribute(STUN_ATTR_USERNAME){ } 38 | Username(std::string name):value(name),Attribute(STUN_ATTR_USERNAME) { } 39 | StringValue value; 40 | }; 41 | 42 | /* --------------------------------------------------------------------- */ 43 | 44 | class Software : public Attribute { 45 | public: 46 | Software():Attribute(STUN_ATTR_SOFTWARE) {} 47 | Software(std::string name):value(name),Attribute(STUN_ATTR_SOFTWARE) {} 48 | StringValue value; 49 | }; 50 | 51 | /* --------------------------------------------------------------------- */ 52 | 53 | class XorMappedAddress : public Attribute { 54 | public: 55 | XorMappedAddress(); 56 | XorMappedAddress(std::string addr, uint16_t p, uint8_t fam = STUN_IP4); 57 | uint8_t family; 58 | uint16_t port; 59 | std::string address; /* IP address in string notation: 192.168.0.1 */ 60 | }; 61 | 62 | /* --------------------------------------------------------------------- */ 63 | 64 | class Fingerprint : public Attribute { 65 | public: 66 | Fingerprint(); 67 | uint32_t crc; 68 | }; 69 | 70 | /* --------------------------------------------------------------------- */ 71 | 72 | class IceControlled : public Attribute { 73 | public: 74 | IceControlled(); 75 | uint64_t tie_breaker; 76 | }; 77 | 78 | /* --------------------------------------------------------------------- */ 79 | 80 | class IceControlling : public Attribute { 81 | public: 82 | IceControlling(); 83 | uint64_t tie_breaker; 84 | }; 85 | 86 | /* --------------------------------------------------------------------- */ 87 | 88 | class Priority : public Attribute { 89 | public: 90 | Priority(); 91 | uint32_t value; 92 | }; 93 | 94 | /* --------------------------------------------------------------------- */ 95 | 96 | class MessageIntegrity : public Attribute { 97 | public: 98 | MessageIntegrity(); 99 | uint8_t sha1[20]; 100 | }; 101 | 102 | } /* namespace stun */ 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /include/stun/Message.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Message 4 | -------- 5 | 6 | Represents a stun::Message. When you're using Message-Integrity and Fingerprint 7 | attributes, make sure to call computeMessageIntegrity(), before you call computeFingerprint(). 8 | The fingerprint (crc32) is computer over the buffer including the message-integrity value, whne 9 | you don't compute this first, the crc will be incorrect. 10 | 11 | */ 12 | #ifndef STUN_MESSAGE_H 13 | #define STUN_MESSAGE_H 14 | 15 | #include 16 | #include 17 | 18 | namespace stun { 19 | 20 | class Message { 21 | public: 22 | Message(uint16_t type = STUN_MSG_TYPE_NONE); 23 | ~Message(); 24 | void addAttribute(Attribute* attr); /* Add an attribute to the message who takes ownership (will delete all attributes in the d'tor. */ 25 | void copyTransactionID(Message* from); /* Copy the transaction ID from the given messsage. */ 26 | void setTransactionID(uint32_t a, uint32_t b, uint32_t c); /* Set the transaction ID from the given values. */ 27 | bool hasAttribute(AttributeType atype); /* Check if the given attribute is found in one of the attributes */ 28 | bool find(MessageIntegrity** result); /* Find a message integrity attribute. */ 29 | bool find(XorMappedAddress** result); /* Find a xor-mapped-address attribute.*/ 30 | bool find(Fingerprint** result); /* Find a fingerprint attrbiute. */ 31 | bool computeMessageIntegrity(std::string key); /* When the message contains a MessageIntegrity element, this will compute the HMAC-SHA1 message integrity. */ 32 | bool computeFingerprint(); /* When the message contains a Fingerprint attriute (must be added after the MessageInterity attribute), this will calculate and set CRC value. Important: make sure that you computer the fingerprint AFTER you've computed the message-integrity */ 33 | 34 | template bool find(uint16_t atype, T** result) { 35 | *result = NULL; 36 | for (size_t i = 0; i < attributes.size(); ++i) { 37 | if (attributes[i]->type == atype) { 38 | *result = static_cast(attributes[i]); 39 | return true; 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | public: 46 | uint16_t type; 47 | uint16_t length; 48 | uint32_t cookie; 49 | uint32_t transaction[3]; 50 | std::vector attributes; 51 | std::vector buffer; 52 | }; 53 | 54 | } /* namespace stun */ 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/stun/Reader.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | STUN 4 | ---- 5 | 6 | Experimental code that parses stun. 7 | 8 | References: 9 | ---------- 10 | - libjingle: https://gist.github.com/roxlu/511544ea07610f70a900 11 | - own test code: https://gist.github.com/roxlu/57fe6c590f6267e0a209 12 | - C++, each attribute has its own class: https://github.com/husman/Development-Sample-Side-Projects/blob/713b052afd2344e95b7e1b33405713460d1b2d95/Computer_Science/My_Hobby_Projects/Live_Streaming/P2P_Live_Streaming/3rdparty/StunUsernameAttribute.h 13 | - C++, each clean example, a couple of generic attribute values: https://github.com/sourcey/libsourcey/blob/f126fdaa26fdcc3f44ebd2d70f2915ee0b6a1b23/src/stun/tests/stuntests.cpp 14 | - Stun attribute values: http://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml 15 | - Some good info on the attributes and their meaning: http://www.3cx.com/blog/voip-howto/stun-details/ 16 | - Test data for message-integrity checks: http://tools.ietf.org/html/rfc5769 17 | */ 18 | 19 | #ifndef STUN_READER_H 20 | #define STUN_READER_H 21 | 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace stun { 31 | 32 | class Reader { 33 | 34 | public: 35 | Reader(); 36 | int process(uint8_t* data, uint32_t nbytes, Message* msg); /* parses the incoming data and fills msg if the data contains a valid stun message, if so it returns 0, when other data is passed into this function it will return 1, on error it returns -1 */ 37 | 38 | private: 39 | uint8_t readU8(); /* read one uint8_t from buffer and increment the index. */ 40 | uint16_t readU16(); /* read an uint16_t from the buffer, expecting the buffer to hold Big Endian data and moving the dx member. */ 41 | uint32_t readU32(); /* read an uint32_t from the buffer, expecting the buffer to hold Big Endian data and moving the dx member. */ 42 | uint64_t readU64(); /* read an uint64_t from the buffer, expecting the buffer to hold Big Endian data and moving the dx member. */ 43 | StringValue readString(uint16_t len); /* read a StringValue from the current buffer */ 44 | XorMappedAddress* readXorMappedAddress(); /* reads a XorMappedAddress */ 45 | void skip(uint32_t nbytes); /* skip the next nbytes. */ 46 | uint32_t bytesLeft(); /* returns the number of bytes that still need to be parsed, this is not the same as the size of the buffer! */ 47 | uint8_t* ptr(); /* returns a pointer to the current read index of the buffer. */ 48 | 49 | public: 50 | std::vector buffer; 51 | size_t dx; 52 | }; 53 | 54 | } /* namespace stun */ 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/stun/Types.h: -------------------------------------------------------------------------------- 1 | #ifndef STUN_TYPES_H 2 | #define STUN_TYPES_H 3 | 4 | #include 5 | #include 6 | 7 | #define STUN_IP4 0x01 8 | #define STUN_IP6 0x02 9 | 10 | namespace stun { 11 | 12 | enum MessageType { 13 | STUN_MSG_TYPE_NONE = 0x0000, 14 | STUN_BINDING_REQUEST = 0x0001, 15 | STUN_BINDING_RESPONSE = 0x0101, 16 | STUN_BINDING_ERROR_RESPONSE = 0x0111, 17 | STUN_BINDING_INDICATION = 0x0011 18 | }; 19 | 20 | enum AttributeType { 21 | STUN_ATTR_TYPE_NONE = 0x0000, 22 | STUN_ATTR_MAPPED_ADDR = 0x0001, 23 | STUN_ATTR_CHANGE_REQ = 0x0003, 24 | STUN_ATTR_USERNAME = 0x0006, 25 | STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, /* See: http://tools.ietf.org/html/rfc5389#section-15.4 + http://tools.ietf.org/html/rfc4013, SHA1, 20 bytes*/ 26 | STUN_ATTR_ERR_CODE = 0x0009, 27 | STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, 28 | STUN_ATTR_CHANNEL_NUMBER = 0x000c, 29 | STUN_ATTR_LIFETIME = 0x000d, 30 | STUN_ATTR_XOR_PEER_ADDR = 0x0012, 31 | STUN_ATTR_DATA = 0x0013, 32 | STUN_ATTR_REALM = 0x0014, 33 | STUN_ATTR_NONCE = 0x0015, 34 | STUN_ATTR_XOR_RELAY_ADDRESS = 0x0016, 35 | STUN_ATTR_REQ_ADDRESS_FAMILY = 0x0017, 36 | STUN_ATTR_EVEN_PORT = 0x0018, 37 | STUN_ATTR_REQUESTED_TRANSPORT = 0x0019, 38 | STUN_ATTR_DONT_FRAGMENT = 0x001a, 39 | STUN_ATTR_XOR_MAPPED_ADDRESS = 0x0020, 40 | STUN_ATTR_RESERVATION_TOKEN = 0x0022, 41 | STUN_ATTR_PRIORITY = 0x0024, /* See: http://tools.ietf.org/html/rfc5245#section-7.1.2.1 */ 42 | STUN_ATTR_USE_CANDIDATE = 0x0025, /* See: http://tools.ietf.org/html/rfc5245#section-7.1.2.1 */ 43 | STUN_ATTR_PADDING = 0x0026, 44 | STUN_ATTR_RESPONSE_PORT = 0x0027, 45 | STUN_ATTR_SOFTWARE = 0x8022, 46 | STUN_ATTR_ALTERNATE_SERVER = 0x8023, 47 | STUN_ATTR_FINGERPRINT = 0x8028, /* See: http://tools.ietf.org/html/rfc5389#section-8 + http://tools.ietf.org/html/rfc5389#section-15.5 */ 48 | STUN_ATTR_ICE_CONTROLLED = 0x8029, /* See: http://tools.ietf.org/html/rfc5245#section-19.1 */ 49 | STUN_ATTR_ICE_CONTROLLING = 0x802a, /* See: http://tools.ietf.org/html/rfc5245#section-19.1 */ 50 | STUN_ATTR_RESPONSE_ORIGIN = 0x802b, 51 | STUN_ATTR_OTHER_ADDRESS = 0x802c, 52 | }; 53 | 54 | /* --------------------------------------------------------------------- */ 55 | 56 | std::string attribute_type_to_string(uint32_t t); 57 | std::string message_type_to_string(uint32_t t); 58 | 59 | /* --------------------------------------------------------------------- */ 60 | 61 | } /* namespace stun */ 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /include/stun/Utils.h: -------------------------------------------------------------------------------- 1 | #ifndef STUN_UTILS_H 2 | #define STUN_UTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace stun { 9 | 10 | /* 11 | Compute the hmac-sha1 over message. 12 | 13 | uint8_t* message: the data over which we compute the hmac sha 14 | uint32_t nbytes: the number of bytse in message 15 | std::string key: key to use for hmac 16 | uint8_t* output: we write the sha1 into this buffer. 17 | */ 18 | bool compute_hmac_sha1(uint8_t* message, uint32_t nbytes, std::string key, uint8_t* output); 19 | 20 | /* 21 | Compute the Message-Integrity of a stun message. 22 | This will not change the given buffer. 23 | 24 | std::vector& buffer: the buffer that contains a valid stun message 25 | std::string key: key to use for hmac 26 | uint8_t* output: will be filled with the correct hmac-sha1 of that represents the integrity message value. 27 | */ 28 | bool compute_message_integrity(std::vector& buffer, std::string key, uint8_t* output); 29 | 30 | /* 31 | Compute the fingerprint value for the stun message. 32 | This will not change the given buffer. 33 | 34 | std::vector& buffer: the buffer that contains a valid stun message. 35 | uint32_t& result: will be set to the calculated crc value. 36 | */ 37 | bool compute_fingerprint(std::vector& buffer, uint32_t& result); 38 | 39 | 40 | } /* namespace stun */ 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/stun/Writer.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | stun::Writer 4 | ------------- 5 | 6 | This will fill the `buffer` member with the binary representation 7 | of the values in the Message. It will also compute the message integrity 8 | and fingerprint CRC32 value when they're found in the attributes of the 9 | Message that is passed into Writer::writeMessage(). 10 | 11 | */ 12 | #ifndef STUN_WRITER_H 13 | #define STUN_WRITER_H 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace stun { 23 | 24 | class Writer { 25 | public: 26 | void writeMessage(Message* msg); 27 | void writeMessage(Message* msg, std::string messageIntegrityPassword); /* When you call this, we assume that the message contains a MessageIntegrity attribute. We calculate the hmac-sha and rewrite our internal buffer. This also checks for a Fingerprint attribute; and computers + writes this crc32-value. */ 28 | 29 | private: 30 | void writeAttribute(Attribute* attr); 31 | void writeUsername(Username* u); 32 | void writeSoftware(Software* s); 33 | void writePriority(Priority* p); 34 | void writeIceControlled(IceControlled* ic); 35 | void writeIceControlling(IceControlling* ic); 36 | void writeMessageIntegrity(MessageIntegrity* integ); 37 | void writeFingerprint(Fingerprint* fp); 38 | void writeXorMappedAddress(XorMappedAddress* xma); 39 | void writeU8(uint8_t v); 40 | void writeU16(uint16_t v); 41 | void writeU32(uint32_t v); 42 | void writeU64(uint64_t v); 43 | void writeBytes(uint8_t* buf, uint32_t nbytes); 44 | void writeString(StringValue v); 45 | void rewriteU16(size_t index, uint16_t v); 46 | void rewriteU32(size_t index, uint32_t v); 47 | 48 | public: 49 | std::vector buffer; 50 | }; 51 | 52 | } /* namespace stun */ 53 | #endif 54 | -------------------------------------------------------------------------------- /include/video/AggregatorVP8.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | AggregatorVP8 4 | ------------- 5 | 6 | Used to reconstruct VP8 frames from multiple RTP-VP8 packets. You 7 | call addPacket() with a initialize PacketVP8. We collect data from the 8 | same frame, from multiple packets into one buffer that can be fed into 9 | the VP8 decoder. 10 | 11 | * this is experimental code * 12 | 13 | */ 14 | #ifndef VIDEO_AGGREGATOR_VP8_H 15 | #define VIDEO_AGGREGATOR_VP8_H 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | enum { 22 | AGGREGATOR_VP8_ERR_PACKET = -1, 23 | AGGREGATOR_VP8_ERR_PAYLOAD = -2, 24 | AGGREGATOR_VP8_ERR_SEQNUM = -3, 25 | AGGREGATOR_VP8_ERR_BUFLEN = -4, 26 | AGGREGATOR_VP8_WANTS_MORE = 1, 27 | AGGREGATOR_VP8_GOT_FRAME = 2 28 | }; 29 | 30 | namespace video { 31 | 32 | std::string aggregator_vp8_result_to_string(int r); 33 | 34 | class AggregatorVP8 { 35 | public: 36 | AggregatorVP8(uint32_t capacity = (1024 * 1024 *2)); 37 | ~AggregatorVP8(); 38 | int addPacket(rtp::PacketVP8* pkt); 39 | 40 | public: 41 | uint32_t capacity; /* we collect data from multiple PacketVP8 into our 'buffer' this is the max size */ 42 | uint8_t* buffer; /* buffer that contains the frame data */ 43 | uint32_t pos; /* current write position */ 44 | uint32_t nbytes; /* number of bytes currently written to the buffer. */ 45 | uint16_t prev_seqnum; /* the previous sequence number that we handled. */ 46 | }; 47 | 48 | } /* namespace video */ 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/video/DecoderVP8.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | DecoderVP8 4 | ---------- 5 | Decodes raw VP8 data. Used to decode the RTP payload data when it's 6 | encoded with VP8. 7 | 8 | */ 9 | #ifndef VIDEO_DECODER_VP8_H 10 | #define VIDEO_DECODER_VP8_H 11 | 12 | #define VPX_CODEC_DISABLE_COMPAT 1 13 | #include 14 | #include 15 | #include 16 | 17 | #define vpx_dx_interface (vpx_codec_vp8_dx()) 18 | 19 | namespace video { 20 | 21 | class DecoderVP8; 22 | typedef void(*decoder_vp8_on_image)(DecoderVP8* dec, const vpx_image_t* img); /* gets called when the decoder decodes a new image */ 23 | 24 | class DecoderVP8 { 25 | 26 | public: 27 | DecoderVP8(); 28 | ~DecoderVP8(); 29 | int init(); 30 | int decode(uint8_t* data, size_t nbytes); 31 | 32 | public: 33 | vpx_codec_ctx_t ctx; 34 | vpx_image_t* img; 35 | bool is_init; 36 | 37 | /* callback */ 38 | decoder_vp8_on_image on_image; 39 | void* user; 40 | }; 41 | 42 | } /* namespace video */ 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/video/EncoderSettings.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_ENCODER_SETTINGS_H 2 | #define VIDEO_ENCODER_SETTINGS_H 3 | 4 | namespace video { 5 | 6 | class EncoderSettings { 7 | 8 | public: 9 | EncoderSettings(); 10 | ~EncoderSettings(); 11 | void reset(); 12 | 13 | public: 14 | int width; 15 | int height; 16 | int fps_num; 17 | int fps_den; 18 | }; 19 | 20 | } /* namespace video */ 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/video/EncoderVP8.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | EncoderVP8 4 | ----------- 5 | 6 | Basic implementation of the VP8 encoder. Used to encode YUV420P data that 7 | one can stream to a WebRTC capable agent. 8 | 9 | Todo 10 | ---- 11 | 12 | Optimize for low latency: 13 | - Discussion: https://groups.google.com/a/webmproject.org/forum/#!topic/webm-discuss/TNPgd7Tf9jQ 14 | - Error resilient: https://gist.github.com/roxlu/ceb1e8c95aff5ba60f45#file-vp8_impl-cc-L225-L238 15 | - VP8 config: https://gist.github.com/roxlu/ceb1e8c95aff5ba60f45#file-vp8_impl-cc-L225-L238 16 | 17 | 18 | */ 19 | 20 | #ifndef VIDEO_ENCODER_VP8_H 21 | #define VIDEO_ENCODER_VP8_H 22 | 23 | #include