├── CMakeLists.txt ├── LICENSE ├── README.md ├── bin └── enc.h264 ├── document └── rtspserver.md ├── src ├── CMakeLists.txt ├── base │ ├── CMakeLists.txt │ ├── Env.cpp │ ├── Env.h │ ├── Mutex.cpp │ ├── Mutex.h │ ├── Mylog.cpp │ ├── Mylog.h │ ├── SignalEvent.cpp │ ├── SignalEvent.h │ ├── TimeEventManager.cpp │ └── TimeEventManager.h └── rtsp │ ├── CMakeLists.txt │ ├── DataBuffer.cpp │ ├── DataBuffer.h │ ├── Event.cpp │ ├── Event.h │ ├── H264FileMediaSource.cpp │ ├── H264FileMediaSource.h │ ├── H264RtpSink.cpp │ ├── H264RtpSink.h │ ├── Ipv4Address.cpp │ ├── Ipv4Address.h │ ├── MediaSession.cpp │ ├── MediaSession.h │ ├── MediaSink.cpp │ ├── MediaSink.h │ ├── MediaSource.cpp │ ├── MediaSource.h │ ├── Receiver.cpp │ ├── Receiver.h │ ├── RtcpInstance.h │ ├── Rtp.h │ ├── RtpInstance.h │ ├── RtpSink.cpp │ ├── RtpSink.h │ ├── RtspConnection.cpp │ ├── RtspConnection.h │ ├── RtspServer.cpp │ ├── RtspServer.h │ ├── SocketOptions.cpp │ ├── SocketOptions.h │ ├── TcpConnect.cpp │ ├── TcpConnect.h │ ├── TcpServer.cpp │ ├── TcpServer.h │ ├── TcpSocket.cpp │ └── TcpSocket.h └── test ├── CMakeLists.txt ├── rtspserver_test.cpp ├── testSignalThread.cpp └── testTimeer.cpp /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(NAS) 2 | CMAKE_MINIMUM_REQUIRED(VERSION 3.2) 3 | 4 | #SET(DAEMON_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/daemon) 5 | #SET(LOG_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/log) 6 | SET(SRC_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/src) 7 | SET(RTSP_SRC_PATHH ${CMAKE_CURRENT_SOURCE_DIR}/src/rtsp) 8 | SET(Base_SRC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/base) 9 | SET(TEST_PATH ${CMAKE_CURRENT_SOURCE_DIR}/test) 10 | SET(ROOT_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/include) 11 | SET(ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 12 | 13 | SET(LIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) 14 | SET(BIN_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin) 15 | 16 | #MESSAGE(STATUS "Project upnp directory:" ${UPNP_TTS_SDK_ROOT_PATHPATH}) 17 | if(DEBUG_FLAG) 18 | SET(DEBUG_FLAG "-g") 19 | SET(BUILD_CONFIGURATION_ "debug") 20 | else() 21 | SET(DEBUG_FLAG "-DNDEBUG") 22 | SET(BUILD_CONFIGURATION "release") 23 | endif() 24 | 25 | SET(HCI_WARNINGS_SETTING "-Wall -Wextra -Wno-missing-field-initializers -Wno-deprecated -Wno-unused-parameter -Wno-deprecated-declarations -Wno-unused-function -Wno-unused-variable") 26 | SET(C_CPP_FLAGS_ "${C_CPP_FLAGS_} -static-libstdc++ -std=c++11 -pthread -g -fPIC -Wl,--no-undefined -O2 -DUSE_COMMON_LIB ${DEBUG_FLAG} ${OS_FLAG} ${HCI_WARNINGS_SETTING}") 27 | 28 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_CPP_FLAGS_}") 29 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CPP_FLAGS_}") 30 | 31 | set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) 32 | 33 | #ADD_SUBDIRECTORY(${LOG_PATH}) 34 | #ADD_SUBDIRECTORY(${DAEMON_PATH}) 35 | ADD_SUBDIRECTORY(${Base_SRC_PATH}) 36 | ADD_SUBDIRECTORY(${RTSP_SRC_PATHH}) 37 | ADD_SUBDIRECTORY(${TEST_PATH}) 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Taoist Luo 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # miniRtspServer 2 | 本开源项目为一个小型的RTSPServer,可以移植到Linux和Android平台 3 | 一. 目录结构介绍 4 | 1. test 包含各个功能的测试代码 5 | 2. bin 可执行文件的生成目录 6 | 3. src 源文件的目录 7 | 4. doc 该文件夹包含本软件的设计文档,系统架构和编程思路 8 | 5. build 该文件为项目的构建目录 9 | 6. lib 该文件夹包含所使用到的库文件 10 | 7. inc 头文件目录 11 | 12 | 二.系统构建 13 | 2.1 Linux 平台 14 | & mkdir build 15 | $ cd build 16 | $ cmake ../ 17 | $ make -j8 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /bin/enc.h264: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TaoistLuo/miniRtspServer/1de66d613941cd036d63ef32e7284ed68cb4b8a4/bin/enc.h264 -------------------------------------------------------------------------------- /document/rtspserver.md: -------------------------------------------------------------------------------- 1 | 1. 本项目旨在学习RTSPSERVER协议 2 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(rtspserver) 2 | 3 | include_directories( 4 | ${RTSP_SRC_PATHH} 5 | ${ROOT_PATH}/src 6 | ) 7 | LINK_DIRECTORIES( 8 | ${ROOT_INCLUDE} 9 | ${RTSP_SRC_PATHH} 10 | ) 11 | AUX_SOURCE_DIRECTORY(./ SRCFILE) 12 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") 13 | link_libraries( 14 | dl 15 | rt 16 | pthread 17 | ) 18 | ADD_LIBRARY( 19 | ${MODULE_NAME} 20 | rtspserver 21 | ${SRCFILE} 22 | ) 23 | -------------------------------------------------------------------------------- /src/base/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(rtspserver) 2 | 3 | include_directories( 4 | ${Base_SRC_PATH} 5 | ${ROOT_PATH}/src 6 | ) 7 | LINK_DIRECTORIES( 8 | ${ROOT_INCLUDE} 9 | ${RTSP_SRC_PATHH} 10 | ) 11 | AUX_SOURCE_DIRECTORY(./ SRCFILE) 12 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") 13 | link_libraries( 14 | dl 15 | rt 16 | pthread 17 | ) 18 | ADD_LIBRARY( 19 | ${MODULE_NAME} 20 | Env 21 | ${SRCFILE} 22 | ) 23 | -------------------------------------------------------------------------------- /src/base/Env.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://editor.csdn.net/md/?articleId=107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include "Env.h" 26 | 27 | 28 | Env::Env() 29 | { 30 | mTimerEventQueue = new TimerEventQueue(); 31 | } 32 | 33 | Env::~Env() 34 | { 35 | delete mTimerEventQueue; 36 | mTimerEventQueue = nullptr; 37 | } 38 | void Env::start(){ 39 | std::thread taskThread(run,mTimerEventQueue); 40 | taskThread.detach(); 41 | return; 42 | } 43 | TimerId Env::addTimer(const TimerEvent& event, uint32_t ms, bool repeat,void*pUser){ 44 | return mTimerEventQueue->addTimer(event,ms,repeat,pUser); 45 | } 46 | void Env::run(void* param){ 47 | TimerEventQueue* timeEventQueue = (TimerEventQueue*)param; 48 | int64_t iTimeRemain = timeEventQueue->getTimeRemaining(); 49 | while(iTimeRemain >= 0) 50 | { 51 | TimeEventManager::mSleep(iTimeRemain); 52 | timeEventQueue->handleTimerEvent(); 53 | iTimeRemain = timeEventQueue->getTimeRemaining(); 54 | } 55 | LOGI("Exit task"); 56 | return; 57 | } -------------------------------------------------------------------------------- /src/base/Env.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _ENV_H__ 26 | #define _ENV_H__ 27 | #include "SignalEvent.h" 28 | #include "TimeEventManager.h" 29 | #include "Mylog.h" 30 | class Env 31 | { 32 | public: 33 | Env(); 34 | ~Env(); 35 | void start(); 36 | TimerId addTimer(const TimerEvent& event, uint32_t ms, bool repeat,void*pUser); 37 | static void run(void* param); 38 | private: 39 | TimerEventQueue* mTimerEventQueue; 40 | }; 41 | 42 | 43 | 44 | #endif -------------------------------------------------------------------------------- /src/base/Mutex.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include "Mutex.h" 26 | #include "Mylog.h" 27 | Mutex* Mutex::createNew() 28 | { 29 | return new Mutex(); 30 | } 31 | 32 | Mutex::Mutex() 33 | { 34 | pthread_mutex_init(&mMutex, NULL); 35 | } 36 | 37 | Mutex::~Mutex() 38 | { 39 | pthread_mutex_destroy(&mMutex); 40 | } 41 | 42 | void Mutex::lock() 43 | { 44 | pthread_mutex_lock(&mMutex); 45 | } 46 | 47 | void Mutex::unlock() 48 | { 49 | pthread_mutex_unlock(&mMutex); 50 | } 51 | 52 | AutoLock::AutoLock(Mutex* mutex) 53 | { 54 | if(!mutex){ 55 | LOGI("lock failed the input was NULL \n"); 56 | return; 57 | } 58 | mMutex=mutex; 59 | mMutex->lock(); 60 | } 61 | 62 | AutoLock::~AutoLock() 63 | { 64 | mMutex->unlock(); 65 | } 66 | -------------------------------------------------------------------------------- /src/base/Mutex.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _MUTEX_H__ 26 | #define _MUTEX_H__ 27 | #include 28 | 29 | class Mutex 30 | { 31 | public: 32 | static Mutex* createNew(); 33 | 34 | Mutex(); 35 | ~Mutex(); 36 | 37 | void lock(); 38 | void unlock(); 39 | 40 | pthread_mutex_t* get() { return &mMutex; }; 41 | 42 | private: 43 | pthread_mutex_t mMutex; 44 | 45 | }; 46 | 47 | class AutoLock 48 | { 49 | public: 50 | AutoLock(Mutex* mutex); 51 | ~AutoLock(); 52 | 53 | private: 54 | Mutex* mMutex; 55 | 56 | }; 57 | 58 | #endif //_MUTEX_H__ -------------------------------------------------------------------------------- /src/base/Mylog.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include "Mylog.h" 26 | char * time2String() { 27 | struct timespec ts; 28 | clock_gettime( CLOCK_REALTIME, &ts); 29 | struct tm * timeinfo = localtime(&ts.tv_sec); 30 | static char timeStr[20]; 31 | sprintf(timeStr, "%.2d-%.2d %.2d:%.2d:%.2d.%.3ld", timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, ts.tv_nsec / 1000000); 32 | return timeStr; 33 | } -------------------------------------------------------------------------------- /src/base/Mylog.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _MYLOG_H__ 26 | #define _MYLOG_H__ 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #define TAG "RTSP" 33 | //#define LOGI printf 34 | char * time2String(); 35 | #define msleep(x) usleep(x*1000) 36 | 37 | #define LOGI(format, ...) printf("%s D %s: [%s:%d] "#format "\n", \ 38 | time2String(), TAG, __FUNCTION__,__LINE__, ##__VA_ARGS__) 39 | #endif -------------------------------------------------------------------------------- /src/base/SignalEvent.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include "SignalEvent.h" 26 | #include "Mylog.h" 27 | SignalEvent::SignalEvent(){ 28 | mMutex = new Mutex(); 29 | mSignal = 0; 30 | } 31 | SignalEvent::~SignalEvent(){ 32 | mSignal = 0; 33 | delete mMutex; 34 | } 35 | 36 | void SignalEvent::start(){ 37 | std::thread taskThread(run,this); 38 | taskThread.detach();; 39 | } 40 | int SignalEvent::getSignal(){ 41 | AutoLock Auto(mMutex); 42 | return mSignal; 43 | } 44 | 45 | void SignalEvent::setSignal(){ 46 | AutoLock Auto(mMutex); 47 | mSignal = 1; 48 | } 49 | void SignalEvent::unsetSignal(){ 50 | AutoLock Auto(mMutex); 51 | mSignal = 0; 52 | } 53 | void SignalEvent::stop(){ 54 | AutoLock Auto(mMutex); 55 | mSignal = 2; 56 | } 57 | void SignalEvent::handleTask(){ 58 | if(signalCallback){ 59 | signalCallback(mParam); 60 | } 61 | 62 | } 63 | void SignalEvent::run(void* param){ 64 | SignalEvent* signalTask = (SignalEvent*)param; 65 | int type = 0; 66 | while(1){ 67 | type = signalTask->getSignal(); 68 | LOGI("sig:%d",type); 69 | switch (type) 70 | { 71 | case NONE: 72 | std::this_thread::sleep_for(std::chrono::microseconds(200)); 73 | break; 74 | case DONOW: 75 | signalTask->handleTask(); 76 | signalTask->unsetSignal(); 77 | std::this_thread::sleep_for(std::chrono::microseconds(200)); 78 | break; 79 | case STOP: 80 | return; 81 | break; 82 | default: 83 | std::this_thread::sleep_for(std::chrono::microseconds(200)); 84 | break; 85 | } 86 | } 87 | 88 | 89 | } 90 | void SignalEvent::setCallBack(const SignlCB& Callback,void* arg){ 91 | AutoLock Auto(mMutex); 92 | mParam = arg; 93 | signalCallback = Callback; 94 | 95 | } -------------------------------------------------------------------------------- /src/base/SignalEvent.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _SIGNAL_H__ 26 | #define _SIGNAL_H__ 27 | #include 28 | #include "string" 29 | #include 30 | #include "Mutex.h" 31 | typedef std::function SignlCB; 32 | 33 | class SignalEvent 34 | { 35 | public: 36 | enum{ 37 | NONE, 38 | DONOW, 39 | STOP, 40 | }; 41 | SignalEvent(); 42 | ~SignalEvent(); 43 | void start(); 44 | int getSignal(); 45 | void setSignal(); 46 | void unsetSignal(); 47 | void stop(); 48 | void handleTask(); 49 | static void run(void* param); 50 | void setCallBack(const SignlCB& Callback,void* arg); 51 | 52 | private: 53 | int mSignal; 54 | SignlCB signalCallback = [](void*){}; 55 | void * mParam; 56 | Mutex* mMutex; 57 | 58 | }; 59 | #endif -------------------------------------------------------------------------------- /src/base/TimeEventManager.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include "TimeEventManager.h" 27 | 28 | 29 | 30 | using namespace std; 31 | using namespace std::chrono; 32 | 33 | TimerId TimerEventQueue::addTimer(const TimerEvent& event, uint32_t ms, bool repeat,void*pUser) 34 | { 35 | std::lock_guard locker(_mutex); 36 | 37 | int64_t timeoutPoint = getTimeNow(); 38 | TimerId timerId = {timeoutPoint+ms, ++_lastTimerId}; 39 | auto timer = make_shared(event, ms, repeat,pUser); 40 | 41 | timer->setNextTimeout(timeoutPoint); 42 | 43 | if(repeat) 44 | { 45 | _repeatTimers.emplace(timerId.second, timer); 46 | } 47 | 48 | _timers.insert(std::pair>(timerId, std::move(timer))); 49 | 50 | return timerId; 51 | } 52 | 53 | void TimerEventQueue::removeTimer(TimerId timerId) 54 | { 55 | std::lock_guard locker(_mutex); 56 | 57 | auto iter = _repeatTimers.find(timerId.second); 58 | if(iter != _repeatTimers.end()) 59 | { 60 | TimerId t = {iter->second->getNextTimeout(), timerId.second}; 61 | _repeatTimers.erase(iter); 62 | _timers.erase(t); 63 | } 64 | else 65 | { 66 | _timers.erase(timerId); 67 | } 68 | } 69 | 70 | int64_t TimerEventQueue::getTimeNow() 71 | { 72 | auto timePoint = steady_clock::now(); 73 | return duration_cast(timePoint.time_since_epoch()).count(); 74 | } 75 | 76 | int64_t TimerEventQueue::getTimeRemaining() 77 | { 78 | std::lock_guard locker(_mutex); 79 | 80 | if(_timers.empty()){ 81 | return -1; 82 | } 83 | 84 | int64_t ms = _timers.begin()->first.first - getTimeNow(); 85 | if(ms <= 0){ 86 | return 0; 87 | } 88 | return ms; 89 | } 90 | 91 | void TimerEventQueue::handleTimerEvent() 92 | { 93 | if(!_timers.empty() || !_repeatTimers.empty()) 94 | { 95 | std::lock_guard locker(_mutex); 96 | 97 | int64_t timePoint = getTimeNow(); 98 | while(!_timers.empty() && _timers.begin()->first.first<=timePoint) 99 | { 100 | _timers.begin()->second->eventCallback(_timers.begin()->second->_pUser); 101 | if(_timers.begin()->second->isRepeat()) 102 | { 103 | _timers.begin()->second->setNextTimeout(timePoint); 104 | TimerId t = {_timers.begin()->second->getNextTimeout(), _timers.begin()->first.second}; 105 | auto timerPtr = std::move(_timers.begin()->second); 106 | _timers.erase(_timers.begin()); 107 | _timers.insert(std::pair>(t, std::move(timerPtr))); 108 | 109 | //_timers.insert(std::pair>(timerId, std::move(timer))); 110 | } 111 | else 112 | { 113 | _timers.erase(_timers.begin()); 114 | } 115 | } 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /src/base/TimeEventManager.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _TIMEEVENTMANAGER_H__ 26 | #define _TIMEEVENTMANAGER_H__ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | 39 | typedef std::function TimerEvent; 40 | typedef std::pair TimerId; 41 | 42 | class TimeEventManager 43 | { 44 | public: 45 | TimeEventManager(const TimerEvent& event, uint32_t ms, bool repeat,void*pUser) 46 | : eventCallback(event) 47 | , _interval(ms) 48 | , _isRepeat(repeat) 49 | ,_pUser(pUser) 50 | { 51 | if (_interval == 0) 52 | _interval = 1; 53 | } 54 | 55 | TimeEventManager() { } 56 | 57 | //get the type of timer 58 | bool isRepeat() const 59 | { 60 | return _isRepeat; 61 | } 62 | 63 | static void mSleep(unsigned ms) 64 | { 65 | std::this_thread::sleep_for(std::chrono::milliseconds(ms)); 66 | } 67 | 68 | void setEventCallback(const TimerEvent& event) 69 | { 70 | eventCallback = event; 71 | } 72 | void setEventCallback(const TimerEvent& event,void* arg) 73 | { 74 | eventCallback = event; 75 | _pUser = arg; 76 | } 77 | //start the timer 78 | void start(int64_t microseconds, bool repeat=false) 79 | { 80 | _isRepeat = repeat; 81 | auto timeBegin = std::chrono::high_resolution_clock::now(); 82 | int64_t elapsed = 0; 83 | 84 | do 85 | { 86 | std::this_thread::sleep_for(std::chrono::microseconds(microseconds - elapsed)); 87 | timeBegin = std::chrono::high_resolution_clock::now(); 88 | eventCallback(_pUser); 89 | elapsed = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - timeBegin).count(); 90 | if (elapsed < 0){ 91 | elapsed = 0; 92 | } 93 | } while (_isRepeat); 94 | } 95 | 96 | void stop() 97 | { 98 | _isRepeat = false; 99 | } 100 | 101 | private: 102 | friend class TimerEventQueue; 103 | 104 | void setNextTimeout(int64_t currentTimePoint) 105 | { 106 | _nextTimeout = currentTimePoint + _interval; 107 | } 108 | 109 | int64_t getNextTimeout() const 110 | { 111 | return _nextTimeout; 112 | } 113 | TimerEvent eventCallback = [](void*){}; 114 | bool _isRepeat = false; 115 | uint32_t _interval = 0; 116 | int64_t _nextTimeout = 0; 117 | void * _pUser; 118 | }; 119 | 120 | class TimerEventQueue 121 | { 122 | public: 123 | TimerId addTimer(const TimerEvent& event, uint32_t ms, bool repeat,void*pUser); 124 | void removeTimer(TimerId timerId); 125 | 126 | // return the latest time of timeout,is not ,return -1 127 | int64_t getTimeRemaining(); 128 | void handleTimerEvent(); 129 | 130 | private: 131 | int64_t getTimeNow(); 132 | 133 | std::mutex _mutex; 134 | std::map> _timers; 135 | std::unordered_map> _repeatTimers; 136 | uint32_t _lastTimerId = 0; 137 | uint32_t _timeRemaining = 0; 138 | }; 139 | 140 | 141 | #endif //end _TIMEEVENTMANAGER_H__ 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /src/rtsp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(rtspserver) 2 | 3 | include_directories( 4 | ${RTSP_SRC_PATHH} 5 | ${ROOT_PATH}/src 6 | ${Base_SRC_PATH} 7 | ) 8 | LINK_DIRECTORIES( 9 | ${ROOT_INCLUDE} 10 | ${RTSP_SRC_PATHH} 11 | ) 12 | AUX_SOURCE_DIRECTORY(./ SRCFILE) 13 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") 14 | link_libraries( 15 | dl 16 | rt 17 | Env 18 | pthread 19 | ) 20 | ADD_LIBRARY( 21 | ${MODULE_NAME} 22 | rtspserver 23 | ${SRCFILE} 24 | ) 25 | -------------------------------------------------------------------------------- /src/rtsp/DataBuffer.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include "DataBuffer.h" 26 | #include "SocketOptions.h" 27 | 28 | #include 29 | #include "Mylog.h" 30 | const int DataBuffer::initialSize = 1024; 31 | const char* DataBuffer::kCRLF = "\r\n"; 32 | 33 | int DataBuffer::read(int fd) 34 | { 35 | char sparebuffer[65536]; 36 | struct iovec vec[2]; 37 | const int writable = writableDataSize(); 38 | vec[0].iov_base = getbufferstart()+mWriteIndex; 39 | vec[0].iov_len = writable; 40 | vec[1].iov_base = sparebuffer; 41 | vec[1].iov_len = sizeof(sparebuffer); 42 | // when there is enough space in this buffer, don't read into sparebuffer. 43 | // when sparebuffer is used, we read 128k-1 bytes at most. 44 | const int iovcnt = (writable < sizeof(sparebuffer)) ? 2 : 1; 45 | const int n = SocketOptions::readv(fd, vec, iovcnt); 46 | LOGI("receive date start*************************************************\n"); 47 | LOGI("Read data length: %d data:\n%s",n,vec[0].iov_base); 48 | LOGI("receive date end -------------------------------------------------\n"); 49 | if (n < 0) 50 | { 51 | return -1; 52 | } 53 | else if (n <= writable) 54 | { 55 | mWriteIndex += n; 56 | } 57 | else 58 | { 59 | mWriteIndex = mBufferSize; 60 | append(sparebuffer, n - writable); 61 | } 62 | 63 | return n; 64 | } 65 | 66 | int DataBuffer::write(int fd) 67 | { 68 | return SocketOptions::write(fd, getReadStart(), readableDataSize()); 69 | } -------------------------------------------------------------------------------- /src/rtsp/DataBuffer.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _BUFFER_H_ 26 | #define _BUFFER_H_ 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | 34 | class DataBuffer 35 | { 36 | public: 37 | static const int initialSize; 38 | 39 | explicit DataBuffer() : 40 | mBufferSize(initialSize), 41 | mReadIndex(0), 42 | mWriteIndex(0) 43 | { 44 | mBuffer = (char*)malloc(mBufferSize); 45 | } 46 | 47 | ~DataBuffer() 48 | { 49 | free(mBuffer); 50 | } 51 | 52 | int readableDataSize() const 53 | { 54 | return mWriteIndex - mReadIndex; 55 | } 56 | 57 | int writableDataSize() const 58 | { 59 | return mBufferSize - mWriteIndex; 60 | } 61 | 62 | int getReadIndex() const 63 | { 64 | return mReadIndex; 65 | } 66 | //get start read point 67 | char* getReadStart() 68 | { 69 | return getbufferstart() + mReadIndex; 70 | } 71 | 72 | const char* getReadStart() const 73 | { 74 | return getbufferstart() + mReadIndex; 75 | } 76 | 77 | const char* lookupCRLF() const 78 | { 79 | const char* crlf = std::search(getReadStart(), getWritePoint(), kCRLF, kCRLF+2); 80 | return crlf == getWritePoint() ? NULL : crlf; 81 | } 82 | 83 | const char* lookupCRLF(const char* start) const 84 | { 85 | assert(getReadStart() <= start); 86 | assert(start <= getWritePoint()); 87 | const char* crlf = std::search(start, getWritePoint(), kCRLF, kCRLF+2); 88 | return crlf == getWritePoint() ? NULL : crlf; 89 | } 90 | 91 | const char* findLastCrlf() const 92 | { 93 | const char* crlf = std::find_end(getReadStart(), getWritePoint(), kCRLF, kCRLF+2); 94 | return crlf == getWritePoint() ? NULL : crlf; 95 | } 96 | 97 | void retrieve(int len) 98 | { 99 | assert(len <= readableDataSize()); 100 | if (len < readableDataSize()) 101 | { 102 | mReadIndex += len; 103 | } 104 | else 105 | { 106 | retrieveAll(); 107 | } 108 | } 109 | 110 | void retrieveUntil(const char* end) 111 | { 112 | assert(getReadStart() <= end); 113 | assert(end <= getWritePoint()); 114 | retrieve(end - getReadStart()); 115 | } 116 | 117 | void retrieveAll() 118 | { 119 | mReadIndex = 0; 120 | mWriteIndex = 0; 121 | } 122 | 123 | char* getWritePoint() 124 | { 125 | return getbufferstart() + mWriteIndex; 126 | } 127 | 128 | const char* getWritePoint() const 129 | { 130 | return getbufferstart() + mWriteIndex; 131 | } 132 | 133 | void hasWritten(int len) 134 | { 135 | assert(len <= writableDataSize()); 136 | mWriteIndex += len; 137 | } 138 | 139 | void unwrite(int len) 140 | { 141 | assert(len <= readableDataSize()); 142 | mWriteIndex -= len; 143 | } 144 | 145 | /* make sure the buffer has enouph space */ 146 | void ensureWritableBytes(int len) 147 | { 148 | if (writableDataSize() < len) 149 | { 150 | makeSpace(len); 151 | } 152 | assert(writableDataSize() >= len); 153 | } 154 | 155 | void makeSpace(int len) 156 | { 157 | if (writableDataSize() + getReadIndex() < len) //如果剩余空间不足 158 | { 159 | mBufferSize = mWriteIndex+len; 160 | mBuffer = (char*)realloc(mBuffer, mBufferSize); 161 | } 162 | else 163 | { 164 | int readable = readableDataSize(); 165 | std::copy(getbufferstart()+mReadIndex, 166 | getbufferstart()+mWriteIndex, 167 | getbufferstart()); 168 | mReadIndex = 0; 169 | mWriteIndex = mReadIndex + readable; 170 | assert(readable == readableDataSize()); 171 | } 172 | } 173 | 174 | void append(const char* data, int len) 175 | { 176 | ensureWritableBytes(len); 177 | //copy data 178 | std::copy(data, data+len, getWritePoint()); 179 | //Reset write position 180 | hasWritten(len); 181 | } 182 | 183 | void append(const void* data, int len) 184 | { 185 | append((const char*)(data), len); 186 | } 187 | 188 | int read(int fd); 189 | int write(int fd); 190 | 191 | private: 192 | char* getbufferstart() 193 | { 194 | return mBuffer; 195 | } 196 | 197 | const char* getbufferstart() const 198 | { return mBuffer; } 199 | 200 | private: 201 | char* mBuffer; 202 | int mBufferSize; 203 | int mReadIndex; 204 | int mWriteIndex; 205 | 206 | static const char* kCRLF; 207 | }; 208 | 209 | #endif //_BUFFER_H_ -------------------------------------------------------------------------------- /src/rtsp/Event.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include "Mylog.h" 27 | #include "Event.h" 28 | #include 29 | 30 | TriggerEvent* TriggerEvent::createNew(void* arg) 31 | { 32 | return new TriggerEvent(arg); 33 | } 34 | 35 | TriggerEvent* TriggerEvent::createNew() 36 | { 37 | return new TriggerEvent(NULL); 38 | } 39 | 40 | TriggerEvent::TriggerEvent(void* arg) : 41 | mArg(arg) 42 | { 43 | 44 | } 45 | 46 | void TriggerEvent::handleEvent() 47 | { 48 | if(mTriggerCallback){ 49 | mTriggerCallback(mArg); 50 | } 51 | } 52 | /* 53 | TimerEvent* TimerEvent::createNew(void* arg) 54 | { 55 | return new TimerEvent(arg); 56 | } 57 | 58 | TimerEvent* TimerEvent::createNew() 59 | { 60 | return new TimerEvent(NULL); 61 | } 62 | 63 | TimerEvent::TimerEvent(void* arg) : 64 | mArg(arg) 65 | { 66 | 67 | } 68 | 69 | void TimerEvent::handleEvent() 70 | { 71 | if(mTimeoutCallback){ 72 | mTimeoutCallback(mArg); 73 | } 74 | 75 | } 76 | void TimerEvent::doTimerEventLoop(void* arg){ 77 | TimerEvent* event = (TimerEvent*)arg; 78 | while (1) 79 | { 80 | msleep(event->mTimeout); 81 | event->handleEvent(); 82 | 83 | } 84 | } 85 | 86 | void TimerEvent::start(){ 87 | std::thread envenTask(doTimerEventLoop,this); 88 | envenTask.detach(); 89 | LOGI("create TimerEventTask thread ok\n"); 90 | return; 91 | } 92 | void TimerEvent::setTimeout(uint32_t timeOut){ 93 | mTimeout = timeOut; 94 | } 95 | */ 96 | IOEvent* IOEvent::createNew(int fd, void* arg) 97 | { 98 | if(fd < 0){ 99 | return NULL; 100 | } 101 | 102 | 103 | return new IOEvent(fd, arg); 104 | } 105 | 106 | IOEvent* IOEvent::createNew(int fd) 107 | { 108 | if(fd < 0){ 109 | return NULL; 110 | } 111 | 112 | 113 | return new IOEvent(fd, NULL); 114 | } 115 | 116 | IOEvent::IOEvent(int fd, void* arg) : 117 | mFd(fd), 118 | mArg(arg), 119 | mEvent(EVENT_NONE), 120 | mREvent(EVENT_NONE), 121 | mReadCallback(NULL), 122 | mWriteCallback(NULL), 123 | mErrorCallback(NULL) 124 | { 125 | 126 | } 127 | 128 | void IOEvent::handleEvent() 129 | { 130 | if (mReadCallback && (mREvent & EVENT_READ)) 131 | { 132 | mReadCallback(mArg); 133 | } 134 | 135 | if (mWriteCallback && (mREvent & EVENT_WRITE)) 136 | { 137 | mWriteCallback(mArg); 138 | } 139 | 140 | if (mErrorCallback && (mREvent & EVENT_ERROR)) 141 | { 142 | mErrorCallback(mArg); 143 | } 144 | } 145 | 146 | void IOEvent::doEventLoop(void* arg){ 147 | IOEvent* event = (IOEvent*)arg; 148 | while (1) 149 | { 150 | msleep(2); 151 | event->handleEvent(); 152 | 153 | } 154 | } 155 | 156 | void IOEvent::start(){ 157 | std::thread envenTask(doEventLoop,this); 158 | envenTask.detach(); 159 | LOGI("create envenTask thread ok\n"); 160 | return; 161 | } -------------------------------------------------------------------------------- /src/rtsp/Event.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _EVENT_H_ 26 | #define _EVENT_H_ 27 | 28 | //#include "base/Logging.h" 29 | 30 | typedef void (*EventCallback)(void*); 31 | 32 | class TriggerEvent 33 | { 34 | public: 35 | static TriggerEvent* createNew(void* arg); 36 | static TriggerEvent* createNew(); 37 | 38 | TriggerEvent(void* arg); 39 | ~TriggerEvent() { }; 40 | 41 | void setArg(void* arg) { mArg = arg; } 42 | void setTriggerCallback(EventCallback cb) { mTriggerCallback = cb; } 43 | void handleEvent(); 44 | 45 | private: 46 | void* mArg; 47 | EventCallback mTriggerCallback; 48 | }; 49 | /* 50 | class TimerEvent 51 | { 52 | public: 53 | static TimerEvent* createNew(void* arg); 54 | static TimerEvent* createNew(); 55 | 56 | TimerEvent(void* arg); 57 | ~TimerEvent() { } 58 | 59 | void setArg(void* arg) { mArg = arg; } 60 | void setTimeoutCallback(EventCallback cb) { mTimeoutCallback = cb; } 61 | void handleEvent(); 62 | static void doTimerEventLoop(void* arg); 63 | void start(); 64 | void setTimeout(uint32_t timeOut); 65 | 66 | private: 67 | void* mArg; 68 | uint32_t mTimeout; 69 | EventCallback mTimeoutCallback; 70 | }; 71 | */ 72 | class IOEvent 73 | { 74 | public: 75 | enum IOEventType 76 | { 77 | EVENT_NONE = 0, 78 | EVENT_READ = 1, 79 | EVENT_WRITE = 2, 80 | EVENT_ERROR = 4, 81 | }; 82 | 83 | static IOEvent* createNew(int fd, void* arg); 84 | static IOEvent* createNew(int fd); 85 | 86 | IOEvent(int fd, void* arg); 87 | ~IOEvent() { } 88 | 89 | int getFd() const { return mFd; } 90 | int getEvent() const { return mEvent; } 91 | void setREvent(int event) { mREvent = event; } 92 | void setArg(void* arg) { mArg = arg; } 93 | 94 | void setReadCallback(EventCallback cb) { mReadCallback = cb; }; 95 | void setWriteCallback(EventCallback cb) { mWriteCallback = cb; }; 96 | void setErrorCallback(EventCallback cb) { mErrorCallback = cb; }; 97 | 98 | void enableReadHandling() { mEvent |= EVENT_READ; } 99 | void enableWriteHandling() { mEvent |= EVENT_WRITE; } 100 | void enableErrorHandling() { mEvent |= EVENT_ERROR; } 101 | void disableReadeHandling() { mEvent &= ~EVENT_READ; } 102 | void disableWriteHandling() { mEvent &= ~EVENT_WRITE; } 103 | void disableErrorHandling() { mEvent &= ~EVENT_ERROR; } 104 | 105 | bool isNoneHandling() const { return mEvent == EVENT_NONE; } 106 | bool isReadHandling() const { return (mEvent & EVENT_READ) != 0; } 107 | bool isWriteHandling() const { return (mEvent & EVENT_WRITE) != 0; } 108 | bool isErrorHandling() const { return (mEvent & EVENT_ERROR) != 0; }; 109 | 110 | void handleEvent(); 111 | static void doEventLoop(void* arg); 112 | void start(); 113 | private: 114 | int mFd; 115 | void* mArg; 116 | int mEvent; 117 | int mREvent; 118 | EventCallback mReadCallback; 119 | EventCallback mWriteCallback; 120 | EventCallback mErrorCallback; 121 | }; 122 | #endif //_EVENT_H_ -------------------------------------------------------------------------------- /src/rtsp/H264FileMediaSource.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "Mylog.h" 31 | #include "H264FileMediaSource.h" 32 | #include "Mutex.h" 33 | 34 | 35 | static inline int startCode3(uint8_t* buf); 36 | static inline int startCode4(uint8_t* buf); 37 | 38 | H264FileMediaSource* H264FileMediaSource::createNew(Env* env,std::string file) 39 | { 40 | return new H264FileMediaSource(env,file); 41 | } 42 | 43 | H264FileMediaSource::H264FileMediaSource(Env* env,const std::string& file) : 44 | MediaSource(env), 45 | mFile(file) 46 | { 47 | mFd = ::open(file.c_str(), O_RDONLY); 48 | assert(mFd > 0); 49 | if(mFd >0){ 50 | LOGI("Open file successful \n"); 51 | setFps(25); 52 | }else{ 53 | LOGI("Open file failed \n"); 54 | exit(0); 55 | } 56 | } 57 | 58 | H264FileMediaSource::~H264FileMediaSource() 59 | { 60 | ::close(mFd); 61 | } 62 | 63 | void H264FileMediaSource::readFrame() 64 | { 65 | AutoLock mAutoLock(mMutex); 66 | 67 | if(mAVFrameInputQueue.empty()){ 68 | return; 69 | } 70 | AVFrame* frame = mAVFrameInputQueue.front(); 71 | 72 | frame->mFrameSize = getFrameFromH264File(mFd, frame->mBuffer, FRAME_MAX_SIZE); 73 | if(frame->mFrameSize < 0) 74 | return; 75 | 76 | if(startCode3(frame->mBuffer)) 77 | { 78 | frame->mFrame = frame->mBuffer+3; 79 | frame->mFrameSize -= 3; 80 | } 81 | else 82 | { 83 | frame->mFrame = frame->mBuffer+4; 84 | frame->mFrameSize -= 4; 85 | } 86 | 87 | mAVFrameInputQueue.pop(); 88 | mAVFrameOutputQueue.push(frame); 89 | } 90 | 91 | static inline int startCode3(uint8_t* buf) 92 | { 93 | if(buf[0] == 0 && buf[1] == 0 && buf[2] == 1) 94 | return 1; 95 | else 96 | return 0; 97 | } 98 | 99 | static inline int startCode4(uint8_t* buf) 100 | { 101 | if(buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 1) 102 | return 1; 103 | else 104 | return 0; 105 | } 106 | 107 | static uint8_t* findNextStartCode(uint8_t* buf, int len) 108 | { 109 | int i; 110 | 111 | if(len < 3) 112 | return NULL; 113 | 114 | for(i = 0; i < len-3; ++i) 115 | { 116 | if(startCode3(buf) || startCode4(buf)) 117 | return buf; 118 | 119 | ++buf; 120 | } 121 | 122 | if(startCode3(buf)) 123 | return buf; 124 | 125 | return NULL; 126 | } 127 | 128 | int H264FileMediaSource::getFrameFromH264File(int fd, uint8_t* frame, int size) 129 | { 130 | int rSize, frameSize; 131 | uint8_t* nextStartCode; 132 | 133 | if(fd < 0) 134 | return fd; 135 | 136 | rSize = read(fd, frame, size); 137 | if(!startCode3(frame) && !startCode4(frame)) 138 | return -1; 139 | 140 | nextStartCode = findNextStartCode(frame+3, rSize-3); 141 | if(!nextStartCode) 142 | { 143 | lseek(fd, 0, SEEK_SET); 144 | frameSize = rSize; 145 | } 146 | else 147 | { 148 | frameSize = (nextStartCode-frame); 149 | lseek(fd, frameSize-rSize, SEEK_CUR); 150 | } 151 | 152 | return frameSize; 153 | } -------------------------------------------------------------------------------- /src/rtsp/H264FileMediaSource.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _H264FILE_MEDIA_SOURCE_H_ 26 | #define _H264FILE_MEDIA_SOURCE_H_ 27 | #include 28 | #include "Mutex.h" 29 | #include "MediaSource.h" 30 | #include "Env.h" 31 | 32 | class H264FileMediaSource : public MediaSource 33 | { 34 | public: 35 | static H264FileMediaSource* createNew(Env* env,std::string file); 36 | 37 | H264FileMediaSource(Env* env,const std::string& file); 38 | ~H264FileMediaSource(); 39 | 40 | protected: 41 | virtual void readFrame(); 42 | 43 | private: 44 | int getFrameFromH264File(int fd, uint8_t* frame, int size); 45 | 46 | private: 47 | std::string mFile; 48 | int mFd; 49 | }; 50 | 51 | #endif //_H264FILE_MEDIA_SOURCE_H_ -------------------------------------------------------------------------------- /src/rtsp/H264RtpSink.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include 27 | 28 | #include "H264RtpSink.h" 29 | #include "Mylog.h" 30 | 31 | H264RtpSink* H264RtpSink::createNew(Env* env,MediaSource* mediaSource) 32 | { 33 | if(!mediaSource){ 34 | return NULL; 35 | } 36 | 37 | 38 | return new H264RtpSink(env,mediaSource); 39 | } 40 | 41 | H264RtpSink::H264RtpSink(Env* env,MediaSource* mediaSource) : 42 | RtpSink(env,mediaSource, RTP_PAYLOAD_TYPE_H264), 43 | mClockRate(90000), 44 | mFps(mediaSource->getFps()) 45 | { 46 | } 47 | 48 | H264RtpSink::~H264RtpSink() 49 | { 50 | 51 | } 52 | 53 | std::string H264RtpSink::getMediaDescription(uint16_t port) 54 | { 55 | char buf[100] = {0}; 56 | sprintf(buf, "m=video %hu RTP/AVP %d", port, mPayloadType); 57 | 58 | return std::string(buf); 59 | } 60 | 61 | std::string H264RtpSink::getAttribute() 62 | { 63 | char buf[100]; 64 | sprintf(buf, "a=rtpmap:%d H264/%d\r\n", mPayloadType, mClockRate); 65 | sprintf(buf+strlen(buf), "a=framerate:%d", mFps); 66 | 67 | return std::string(buf); 68 | } 69 | 70 | void H264RtpSink::handleFrame(AVFrame* frame) 71 | { 72 | RtpHeader* rtpHeader = mRtpPacket.mRtpHeadr; 73 | uint8_t naluType = frame->mFrame[0]; 74 | 75 | if(frame->mFrameSize <= RTP_MAX_PKT_SIZE) 76 | { 77 | memcpy(rtpHeader->payload, frame->mFrame, frame->mFrameSize); 78 | mRtpPacket.mSize = frame->mFrameSize; 79 | sendRtpPacket(&mRtpPacket); 80 | mSeq++; 81 | 82 | if ((naluType & 0x1F) == 7 || (naluType & 0x1F) == 8) // 如果是SPS、PPS就不需要加时间戳 83 | return; 84 | } 85 | else 86 | { 87 | int pktNum = frame->mFrameSize / RTP_MAX_PKT_SIZE; // 有几个完整的包 88 | int remainPktSize = frame->mFrameSize % RTP_MAX_PKT_SIZE; // 剩余不完整包的大小 89 | int i, pos = 1; 90 | 91 | /* 发送完整的包 */ 92 | for (i = 0; i < pktNum; i++) 93 | { 94 | /* 95 | * FU Indicator 96 | * 0 1 2 3 4 5 6 7 97 | * +-+-+-+-+-+-+-+-+ 98 | * |F|NRI| Type | 99 | * +---------------+ 100 | * */ 101 | rtpHeader->payload[0] = (naluType & 0x60) | 28; //(naluType & 0x60)表示nalu的重要性,28表示为分片 102 | 103 | /* 104 | * FU Header 105 | * 0 1 2 3 4 5 6 7 106 | * +-+-+-+-+-+-+-+-+ 107 | * |S|E|R| Type | 108 | * +---------------+ 109 | * */ 110 | rtpHeader->payload[1] = naluType & 0x1F; 111 | 112 | if (i == 0) //第一包数据 113 | rtpHeader->payload[1] |= 0x80; // start 114 | else if (remainPktSize == 0 && i == pktNum - 1) //最后一包数据 115 | rtpHeader->payload[1] |= 0x40; // end 116 | 117 | memcpy(rtpHeader->payload+2, frame->mFrame+pos, RTP_MAX_PKT_SIZE); 118 | mRtpPacket.mSize = RTP_MAX_PKT_SIZE+2; 119 | sendRtpPacket(&mRtpPacket); 120 | 121 | mSeq++; 122 | pos += RTP_MAX_PKT_SIZE; 123 | } 124 | 125 | /* 发送剩余的数据 */ 126 | if (remainPktSize > 0) 127 | { 128 | rtpHeader->payload[0] = (naluType & 0x60) | 28; 129 | rtpHeader->payload[1] = naluType & 0x1F; 130 | rtpHeader->payload[1] |= 0x40; //end 131 | 132 | memcpy(rtpHeader->payload+2, frame->mFrame+pos, remainPktSize); 133 | mRtpPacket.mSize = remainPktSize+2; 134 | sendRtpPacket(&mRtpPacket); 135 | 136 | mSeq++; 137 | } 138 | } 139 | 140 | mTimestamp += mClockRate/mFps; 141 | } 142 | -------------------------------------------------------------------------------- /src/rtsp/H264RtpSink.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _H264_MEDIA_SINK_H_ 26 | #define _H264_MEDIA_SINK_H_ 27 | #include 28 | #include "Env.h" 29 | #include "RtpSink.h" 30 | 31 | class H264RtpSink : public RtpSink 32 | { 33 | public: 34 | static H264RtpSink* createNew(Env* env,MediaSource* mediaSource); 35 | 36 | H264RtpSink(Env* env,MediaSource* mediaSource); 37 | virtual ~H264RtpSink(); 38 | 39 | virtual std::string getMediaDescription(uint16_t port); 40 | virtual std::string getAttribute(); 41 | virtual void handleFrame(AVFrame* frame); 42 | 43 | private: 44 | RtpPacket mRtpPacket; 45 | int mClockRate; 46 | int mFps; 47 | 48 | }; 49 | 50 | #endif //_H264_MEDIA_SINK_H_ -------------------------------------------------------------------------------- /src/rtsp/Ipv4Address.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include "Ipv4Address.h" 26 | 27 | Ipv4Address::Ipv4Address() 28 | { 29 | mPort = 8554; 30 | mAddr.sin_family = AF_INET; 31 | mAddr.sin_addr.s_addr = htonl(INADDR_ANY); 32 | mAddr.sin_port = htons(8554); 33 | } 34 | Ipv4Address::Ipv4Address(uint16_t port) 35 | { 36 | mPort = port; 37 | mAddr.sin_family = AF_INET; 38 | mAddr.sin_addr.s_addr = htonl(INADDR_ANY); 39 | mAddr.sin_port = htons(port); 40 | } 41 | 42 | Ipv4Address::Ipv4Address(std::string ip, uint16_t port) : 43 | mIp(ip), 44 | mPort(port) 45 | { 46 | mAddr.sin_family = AF_INET; 47 | mAddr.sin_addr.s_addr = inet_addr(ip.c_str()); 48 | mAddr.sin_port = htons(port); 49 | } 50 | 51 | void Ipv4Address::setAddr(std::string ip, uint16_t port) 52 | { 53 | mIp = ip; 54 | mPort = port; 55 | mAddr.sin_family = AF_INET; 56 | mAddr.sin_addr.s_addr = inet_addr(ip.c_str()); 57 | mAddr.sin_port = htons(port); 58 | } 59 | 60 | std::string Ipv4Address::getIp() 61 | { 62 | return mIp; 63 | } 64 | 65 | uint16_t Ipv4Address::getPort() 66 | { 67 | return mPort; 68 | } 69 | 70 | struct sockaddr* Ipv4Address::getAddr() 71 | { 72 | return (struct sockaddr*)&mAddr; 73 | } 74 | -------------------------------------------------------------------------------- /src/rtsp/Ipv4Address.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _INET_ADDRESS_H_ 26 | #define _INET_ADDRESS_H_ 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | class Ipv4Address 34 | { 35 | public: 36 | Ipv4Address(); 37 | Ipv4Address(uint16_t port); 38 | Ipv4Address(std::string ip, uint16_t port); 39 | void setAddr(std::string ip, uint16_t port); 40 | std::string getIp(); 41 | uint16_t getPort(); 42 | struct sockaddr* getAddr(); 43 | 44 | private: 45 | std::string mIp; 46 | uint16_t mPort; 47 | struct sockaddr_in mAddr; 48 | }; 49 | 50 | #endif //_INET_ADDRESS_H_ -------------------------------------------------------------------------------- /src/rtsp/MediaSession.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "MediaSession.h" 32 | #include "SocketOptions.h" 33 | #include "Mylog.h" 34 | #include 35 | #include 36 | #include 37 | 38 | MediaSession* MediaSession::createNew(std::string sessionName) 39 | { 40 | return new MediaSession(sessionName); 41 | } 42 | 43 | MediaSession::MediaSession(const std::string& sessionName) : 44 | mSessionName(sessionName), 45 | mIsStartMulticast(false) 46 | { 47 | mTracks[0].mTrackId = TrackId0; 48 | mTracks[1].mTrackId = TrackId1; 49 | mTracks[0].mIsAlive = false; 50 | mTracks[1].mIsAlive = false; 51 | 52 | for(int i = 0; i < MEDIA_MAX_TRACK_NUM; ++i) 53 | { 54 | mMulticastRtpInstances[i] = NULL; 55 | mMulticastRtcpInstances[i] = NULL; 56 | } 57 | } 58 | 59 | MediaSession::~MediaSession() 60 | { 61 | for(int i = 0; i < MEDIA_MAX_TRACK_NUM; ++i) 62 | { 63 | if(mMulticastRtpInstances[i]) 64 | { 65 | this->removeRtpInstance(mMulticastRtpInstances[i]); 66 | delete mMulticastRtpInstances[i]; 67 | } 68 | 69 | if(mMulticastRtcpInstances[i]){ 70 | delete mMulticastRtcpInstances[i]; 71 | } 72 | } 73 | } 74 | 75 | std::string MediaSession::generateSDPDescription() 76 | { 77 | if(!mSdp.empty()) 78 | return mSdp; 79 | 80 | std::string ip = SocketOptions::getLocalIp(); 81 | char buf[2048] = {0}; 82 | 83 | snprintf(buf, sizeof(buf), 84 | "v=0\r\n" 85 | "o=- 9%ld 1 IN IP4 %s\r\n" 86 | "t=0 0\r\n" 87 | "a=control:*\r\n" 88 | "a=type:broadcast\r\n", 89 | (long)time(NULL), ip.c_str()); 90 | 91 | if(isStartMulticast()) 92 | { 93 | snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), 94 | "a=rtcp-unicast: reflection\r\n"); 95 | } 96 | 97 | for(int i = 0; i < MEDIA_MAX_TRACK_NUM; ++i) 98 | { 99 | uint16_t port = 0; 100 | 101 | if(mTracks[i].mIsAlive != true) 102 | continue; 103 | 104 | if(isStartMulticast()) 105 | port = getMulticastDestRtpPort((TrackId)i); 106 | 107 | snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), 108 | "%s\r\n", mTracks[i].mRtpSink->getMediaDescription(port).c_str()); 109 | 110 | if(isStartMulticast()) 111 | snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), 112 | "c=IN IP4 %s/255\r\n", getMulticastDestAddr().c_str()); 113 | else 114 | snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), 115 | "c=IN IP4 0.0.0.0\r\n"); 116 | 117 | snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), 118 | "%s\r\n", mTracks[i].mRtpSink->getAttribute().c_str()); 119 | 120 | snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), 121 | "a=control:track%d\r\n", mTracks[i].mTrackId); 122 | } 123 | 124 | mSdp = buf; 125 | LOGI("sdp: %s",mSdp.c_str()); 126 | return mSdp; 127 | } 128 | 129 | MediaSession::Track* MediaSession::getTrack(MediaSession::TrackId trackId) 130 | { 131 | for(int i = 0; i < MEDIA_MAX_TRACK_NUM; ++i) 132 | { 133 | if(mTracks[i].mTrackId == trackId) 134 | return &mTracks[i]; 135 | } 136 | 137 | return NULL; 138 | } 139 | 140 | bool MediaSession::addRtpSink(MediaSession::TrackId trackId, RtpSink* rtpSink) 141 | { 142 | 143 | Track* track; 144 | 145 | track = getTrack(trackId); 146 | if(!track) 147 | return false; 148 | 149 | track->mRtpSink = rtpSink; 150 | track->mIsAlive = true; 151 | 152 | rtpSink->setSendFrameCallback(sendPacketCallback, this, track); 153 | 154 | return true; 155 | } 156 | 157 | bool MediaSession::addRtpInstance(MediaSession::TrackId trackId, RtpInstance* rtpInstance) 158 | { 159 | Track* track = getTrack(trackId); 160 | if(!track || track->mIsAlive != true) 161 | return false; 162 | 163 | track->mRtpInstances.push_back(rtpInstance); 164 | 165 | return true; 166 | } 167 | 168 | bool MediaSession::removeRtpInstance(RtpInstance* rtpInstance) 169 | { 170 | for(int i = 0; i < MEDIA_MAX_TRACK_NUM; ++i) 171 | { 172 | if(mTracks[i].mIsAlive == false) 173 | continue; 174 | 175 | std::list::iterator it = std::find(mTracks[i].mRtpInstances.begin(), 176 | mTracks[i].mRtpInstances.end(), 177 | rtpInstance); 178 | if(it == mTracks[i].mRtpInstances.end()) 179 | continue; 180 | 181 | mTracks[i].mRtpInstances.erase(it); 182 | return true; 183 | } 184 | 185 | return false; 186 | } 187 | 188 | void MediaSession::sendPacketCallback(void* arg1, void* arg2, RtpPacket* rtpPacket) 189 | { 190 | MediaSession* mediaSession = (MediaSession*)arg1; 191 | MediaSession::Track* track = (MediaSession::Track*)arg2; 192 | 193 | mediaSession->sendPacket(track, rtpPacket); 194 | } 195 | 196 | void MediaSession::sendPacket(MediaSession::Track* track, RtpPacket* rtpPacket) 197 | { 198 | std::list::iterator it; 199 | 200 | for(it = track->mRtpInstances.begin(); it != track->mRtpInstances.end(); ++it) 201 | { 202 | if((*it)->alive() == true) 203 | { 204 | (*it)->send(rtpPacket); 205 | } 206 | } 207 | } 208 | 209 | bool MediaSession::startMulticast() 210 | { 211 | /* 随机生成多播地址 */ 212 | struct sockaddr_in addr = { 0 }; 213 | uint32_t range = 0xE8FFFFFF - 0xE8000100; 214 | addr.sin_addr.s_addr = htonl(0xE8000100 + (rand()) % range); 215 | mMulticastAddr = inet_ntoa(addr.sin_addr); 216 | 217 | int rtpSockfd1, rtcpSockfd1; 218 | int rtpSockfd2, rtcpSockfd2; 219 | uint16_t rtpPort1, rtcpPort1; 220 | uint16_t rtpPort2, rtcpPort2; 221 | bool ret; 222 | 223 | rtpSockfd1 = SocketOptions::createUdpSocket(); 224 | assert(rtpSockfd1 > 0); 225 | 226 | rtpSockfd2 = SocketOptions::createUdpSocket(); 227 | assert(rtpSockfd2 > 0); 228 | 229 | rtcpSockfd1 = SocketOptions::createUdpSocket(); 230 | assert(rtcpSockfd1 > 0); 231 | 232 | rtcpSockfd2 = SocketOptions::createUdpSocket(); 233 | assert(rtcpSockfd2 > 0); 234 | 235 | uint16_t port = rand() & 0xfffe; 236 | if(port < 10000){ 237 | port += 10000; 238 | } 239 | 240 | rtpPort1 = port; 241 | rtcpPort1 = port+1; 242 | rtpPort2 = rtcpPort1+1; 243 | rtcpPort2 = rtpPort2+1; 244 | 245 | mMulticastRtpInstances[TrackId0] = RtpInstance::createNewOverUdp(rtpSockfd1, 0, mMulticastAddr, rtpPort1); 246 | mMulticastRtpInstances[TrackId1] = RtpInstance::createNewOverUdp(rtpSockfd2, 0, mMulticastAddr, rtpPort2); 247 | mMulticastRtcpInstances[TrackId0] = RtcpInstance::createNew(rtcpSockfd1, 0, mMulticastAddr, rtcpPort1); 248 | mMulticastRtcpInstances[TrackId1] = RtcpInstance::createNew(rtcpSockfd2, 0, mMulticastAddr, rtcpPort2); 249 | 250 | this->addRtpInstance(TrackId0, mMulticastRtpInstances[TrackId0]); 251 | this->addRtpInstance(TrackId1, mMulticastRtpInstances[TrackId1]); 252 | mMulticastRtpInstances[TrackId0]->setAlive(true); 253 | mMulticastRtpInstances[TrackId1]->setAlive(true); 254 | 255 | mIsStartMulticast = true; 256 | 257 | return true; 258 | } 259 | 260 | bool MediaSession::isStartMulticast() 261 | { 262 | return mIsStartMulticast; 263 | } 264 | 265 | uint16_t MediaSession::getMulticastDestRtpPort(TrackId trackId) 266 | { 267 | if(trackId > TrackId1 || !mMulticastRtpInstances[trackId]) 268 | return -1; 269 | 270 | return mMulticastRtpInstances[trackId]->getPeerPort(); 271 | } -------------------------------------------------------------------------------- /src/rtsp/MediaSession.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _MEDIASESSION_H_ 26 | #define _MEDIASESSION_H_ 27 | #include 28 | #include 29 | 30 | #include "RtpInstance.h" 31 | #include "RtcpInstance.h" 32 | #include "RtpSink.h" 33 | 34 | #define MEDIA_MAX_TRACK_NUM 2 35 | 36 | class MediaSession 37 | { 38 | public: 39 | enum TrackId 40 | { 41 | TrackIdNone = -1, 42 | TrackId0 = 0, 43 | TrackId1 = 1, 44 | }; 45 | 46 | static MediaSession* createNew(std::string sessionName); 47 | 48 | MediaSession(const std::string& sessionName); 49 | ~MediaSession(); 50 | 51 | std::string name() const { return mSessionName; } 52 | std::string generateSDPDescription(); 53 | bool addRtpSink(MediaSession::TrackId trackId, RtpSink* rtpSink); 54 | bool addRtpInstance(MediaSession::TrackId trackId, RtpInstance* rtpInstance); 55 | bool removeRtpInstance(RtpInstance* rtpInstance); 56 | bool startMulticast(); 57 | bool isStartMulticast(); 58 | std::string getMulticastDestAddr() const { return mMulticastAddr; } 59 | uint16_t getMulticastDestRtpPort(TrackId trackId); 60 | 61 | public: 62 | class Track 63 | { 64 | public: 65 | RtpSink* mRtpSink; 66 | int mTrackId; 67 | bool mIsAlive; 68 | std::list mRtpInstances; 69 | }; 70 | 71 | Track* getTrack(MediaSession::TrackId trackId); 72 | static void sendPacketCallback(void* arg1, void* arg2, RtpPacket* rtpPacket); 73 | void sendPacket(MediaSession::Track* tarck, RtpPacket* rtpPacket); 74 | 75 | private: 76 | std::string mSessionName; 77 | std::string mSdp; 78 | Track mTracks[MEDIA_MAX_TRACK_NUM]; 79 | bool mIsStartMulticast; 80 | std::string mMulticastAddr; 81 | RtpInstance* mMulticastRtpInstances[MEDIA_MAX_TRACK_NUM]; 82 | RtcpInstance* mMulticastRtcpInstances[MEDIA_MAX_TRACK_NUM]; 83 | }; 84 | 85 | #endif //_MEDIASESSION_H_ -------------------------------------------------------------------------------- /src/rtsp/MediaSink.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TaoistLuo/miniRtspServer/1de66d613941cd036d63ef32e7284ed68cb4b8a4/src/rtsp/MediaSink.cpp -------------------------------------------------------------------------------- /src/rtsp/MediaSink.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TaoistLuo/miniRtspServer/1de66d613941cd036d63ef32e7284ed68cb4b8a4/src/rtsp/MediaSink.h -------------------------------------------------------------------------------- /src/rtsp/MediaSource.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include "MediaSource.h" 26 | #include "Mylog.h" 27 | MediaSource::MediaSource(Env* env):mEnv(env) 28 | { 29 | mMutex = Mutex::createNew(); 30 | for(int i = 0; i < DEFAULT_FRAME_NUM; ++i){ 31 | mAVFrameInputQueue.push(&mAVFrames[i]); 32 | } 33 | setFps(25); 34 | uint32_t frameTime = 1000/25; 35 | mEnv->addTimer(taskCallback,frameTime,true,this); 36 | } 37 | 38 | MediaSource::~MediaSource() 39 | { 40 | } 41 | 42 | AVFrame* MediaSource::getFrame() 43 | { 44 | AutoLock mAutoLock(mMutex); 45 | if(mAVFrameOutputQueue.empty()) 46 | { 47 | LOGI("mAVFrameOutputQueue was NULL\n"); 48 | return NULL; 49 | } 50 | AVFrame* frame = mAVFrameOutputQueue.front(); 51 | mAVFrameOutputQueue.pop(); 52 | return frame; 53 | } 54 | 55 | void MediaSource::putFrame(AVFrame* frame) 56 | { 57 | AutoLock mAutoLock(mMutex); 58 | mAVFrameInputQueue.push(frame); 59 | } 60 | 61 | 62 | void MediaSource::taskCallback(void* arg) 63 | { 64 | MediaSource* source = (MediaSource*)arg; 65 | source->readFrame(); 66 | } 67 | void MediaSource::start(uint32_t ms) 68 | { 69 | //mTimerEvent->setTimeout((uint32_t)ms); 70 | mTimerEvent->start(ms*1000, true); 71 | } -------------------------------------------------------------------------------- /src/rtsp/MediaSource.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _MEDIA_SOURCE_H_ 26 | #define _MEDIA_SOURCE_H_ 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "Mutex.h" 33 | #include "Event.h" 34 | #include "TimeEventManager.h" 35 | #include "SignalEvent.h" 36 | #include "Env.h" 37 | 38 | #define FRAME_MAX_SIZE (1024*500) 39 | #define DEFAULT_FRAME_NUM 4 40 | class AVFrame1 41 | { 42 | public: 43 | AVFrame1(int framesize,char* frame) { 44 | mFrame = new char[framesize], 45 | memcpy(mFrame,frame,framesize); 46 | mFrameSize = framesize; 47 | } 48 | 49 | ~AVFrame1() 50 | { delete mBuffer; } 51 | 52 | char* mBuffer; 53 | char* mFrame; 54 | int mFrameSize; 55 | }; 56 | class AVFrame 57 | { 58 | public: 59 | AVFrame() : 60 | mBuffer(new uint8_t[FRAME_MAX_SIZE]), 61 | mFrameSize(0) 62 | { } 63 | 64 | ~AVFrame() 65 | { delete mBuffer; } 66 | 67 | uint8_t* mBuffer; 68 | uint8_t* mFrame; 69 | int mFrameSize; 70 | }; 71 | 72 | class MediaSource 73 | { 74 | public: 75 | virtual ~MediaSource(); 76 | 77 | AVFrame* getFrame(); 78 | void putFrame(AVFrame* frame); 79 | int getFps() const { return mFps; } 80 | void start(uint32_t ms); 81 | 82 | protected: 83 | MediaSource(Env* env); 84 | virtual void readFrame() = 0; 85 | void setFps(int fps) { mFps = fps; } 86 | 87 | private: 88 | static void taskCallback(void*); 89 | 90 | protected: 91 | Env* mEnv; 92 | AVFrame mAVFrames[DEFAULT_FRAME_NUM]; 93 | std::queue mAVFrameInputQueue; 94 | std::queue mAVFrameOutputQueue; 95 | Mutex* mMutex; 96 | int mFps; 97 | //TimerEvent* mTimerEvent; 98 | TimeEventManager* mTimerEvent; 99 | }; 100 | 101 | #endif //_MEDIA_SOURCE_H_ -------------------------------------------------------------------------------- /src/rtsp/Receiver.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "Receiver.h" 30 | #include "SocketOptions.h" 31 | #include "Mylog.h" 32 | 33 | #define msleep(x) usleep(x*1000) 34 | 35 | Receiver* Receiver::createNew(const Ipv4Address& addr) 36 | { 37 | return new Receiver(addr); 38 | } 39 | 40 | Receiver::Receiver(const Ipv4Address& addr) : 41 | mAddr(addr), 42 | mSocket(SocketOptions::createTcpSocket()), 43 | mNewConnectionCallback(NULL) 44 | { 45 | //mSiganalThread = new SignalEvent(); 46 | mSocket.setReuseAddr(1); 47 | mSocket.bind(mAddr); 48 | } 49 | 50 | Receiver::~Receiver() 51 | { 52 | 53 | } 54 | 55 | void Receiver::listen() 56 | { 57 | mListenning = true; 58 | mSocket.listen(1024); 59 | LOGI("listen ok\n"); 60 | } 61 | 62 | void Receiver::setNewConnectionCallback(NewConnectionCallback cb, void* arg) 63 | { 64 | mNewConnectionCallback = cb; 65 | mArg = arg; 66 | } 67 | 68 | void Receiver::readCallback(void* arg) 69 | { 70 | Receiver* receiver = (Receiver*)arg; 71 | receiver->handleRead(); 72 | } 73 | 74 | void Receiver::handleRead() 75 | { 76 | // int connfd = mSocket.accept(); 77 | // LOGI("client connect: %d\n", connfd); 78 | // if(mNewConnectionCallback) 79 | // mNewConnectionCallback(mArg, connfd); 80 | } 81 | int Receiver::acceptClient(int sockfd, char* ip, int* port){ 82 | int clientfd; 83 | socklen_t len = 0; 84 | struct sockaddr_in addr; 85 | 86 | memset(&addr, 0, sizeof(addr)); 87 | len = sizeof(addr); 88 | 89 | clientfd = accept(sockfd, (struct sockaddr *)&addr, &len); 90 | if(clientfd < 0){ 91 | // LOGI("receive msg from client erro!\n"); 92 | return -1; 93 | } 94 | strcpy(ip, inet_ntoa(addr.sin_addr)); 95 | *port = ntohs(addr.sin_port); 96 | 97 | return clientfd; 98 | } 99 | void Receiver::acceptthread(void* accept){ 100 | if(accept == NULL){ 101 | LOGI("Receiver is NULL ,error\n"); 102 | return; 103 | } 104 | Receiver* receiver = (Receiver*)accept; 105 | int serverSocketfd = receiver->getSocketfd(); 106 | LOGI("Start do loop\n"); 107 | while (1) 108 | { 109 | int fd; 110 | char clientIp[40]; 111 | int port; 112 | fd = acceptClient(serverSocketfd, clientIp, &port); 113 | if(fd == -1){ 114 | msleep(500); 115 | continue; 116 | } 117 | ClientInfo* clientinfo = new ClientInfo(fd,clientIp,port); 118 | receiver->doClientConnectCallback(clientinfo); 119 | LOGI("connect to client successful!\n"); 120 | msleep(500); 121 | } 122 | 123 | } 124 | int Receiver::getSocketfd(){ 125 | return mSocket.getSocketFd(); 126 | } 127 | void Receiver::doClient(){ 128 | std::thread accept(acceptthread,this); 129 | accept.detach(); 130 | LOGI("create doClient thread ok\n"); 131 | } 132 | void Receiver::doClientConnectCallback(ClientInfo* data){ 133 | mNewConnectionCallback(mArg,data); 134 | } 135 | 136 | -------------------------------------------------------------------------------- /src/rtsp/Receiver.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _ACCEPTOR_H__ 26 | #define _ACCEPTOR_H__ 27 | #include 28 | #include "Ipv4Address.h" 29 | #include "SocketOptions.h" 30 | #include "TcpSocket.h" 31 | #include "SignalEvent.h" 32 | 33 | struct ClientInfo{ 34 | int clientSockfd; 35 | char clientIp[40]; 36 | int clientPort; 37 | ClientInfo(int fd, char* Ip,int port){ 38 | clientSockfd = fd; 39 | memset(clientIp,0,40); 40 | strcpy(clientIp,Ip); 41 | clientPort = port; 42 | } 43 | }; 44 | 45 | class Receiver 46 | { 47 | public: 48 | typedef void(*NewConnectionCallback)(void *tcpserver, ClientInfo* data); 49 | 50 | static Receiver* createNew(const Ipv4Address& addr); 51 | 52 | Receiver(const Ipv4Address& addr); 53 | ~Receiver(); 54 | 55 | bool listenning() const { return mListenning; } 56 | void listen(); 57 | void setNewConnectionCallback(NewConnectionCallback cb, void* arg); 58 | static void acceptthread(void* accept); 59 | static int acceptClient(int sockfd, char* ip, int* port); 60 | int getSocketfd(); 61 | void doClient(); 62 | void doClientConnectCallback(ClientInfo* data); 63 | private: 64 | static void readCallback(void*); 65 | void handleRead(); 66 | 67 | private: 68 | Ipv4Address mAddr; 69 | TcpSocket mSocket; 70 | bool mListenning; 71 | NewConnectionCallback mNewConnectionCallback; 72 | SignalEvent* mSiganalThread; 73 | void* mArg; 74 | }; 75 | #endif -------------------------------------------------------------------------------- /src/rtsp/RtcpInstance.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _RTCP_H_ 26 | #define _RTCP_H_ 27 | #include 28 | #include 29 | #include 30 | 31 | #include "Ipv4Address.h" 32 | #include "SocketOptions.h" 33 | class RtcpInstance 34 | { 35 | public: 36 | static RtcpInstance* createNew(int localSockfd, uint16_t localPort, 37 | std::string destIp, uint16_t destPort) 38 | { 39 | return new RtcpInstance(localSockfd, localPort, destIp, destPort); 40 | } 41 | 42 | ~RtcpInstance() 43 | { 44 | SocketOptions::close(mServerSockfd); 45 | } 46 | 47 | int send(void* buf, int size) 48 | { 49 | return SocketOptions::sendto(mServerSockfd, buf, size, mDestAddr.getAddr()); 50 | } 51 | 52 | int recv(void* buf, int size, Ipv4Address* addr) 53 | { 54 | return 0; 55 | } 56 | 57 | uint16_t getLocalPort() const { return mLocalPort; } 58 | 59 | int alive() const { return mIsAlive; } 60 | int setAlive(bool alive) { mIsAlive = alive; }; 61 | void setSessionId(uint16_t sessionId) { mSessionId = sessionId; } 62 | uint16_t sessionId() const { return mSessionId; } 63 | 64 | public: 65 | RtcpInstance(int localSockfd, uint16_t localPort, 66 | std::string destIp, uint16_t destPort) : 67 | mServerSockfd(localSockfd), mLocalPort(localPort), mDestAddr(destIp, destPort), 68 | mIsAlive(false), mSessionId(0) 69 | { } 70 | 71 | private: 72 | int mServerSockfd; 73 | uint16_t mLocalPort; 74 | Ipv4Address mDestAddr; 75 | bool mIsAlive; 76 | uint16_t mSessionId; 77 | }; 78 | 79 | 80 | #endif -------------------------------------------------------------------------------- /src/rtsp/Rtp.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _RTP_H_ 26 | #define _RTP_H_ 27 | #include 28 | #include 29 | 30 | #define RTP_VESION 2 31 | 32 | #define RTP_PAYLOAD_TYPE_H264 96 33 | #define RTP_PAYLOAD_TYPE_AAC 97 34 | 35 | #define RTP_HEADER_SIZE 12 36 | #define RTP_MAX_PKT_SIZE 1400 37 | 38 | struct RtpHeader 39 | { 40 | /* byte 0 */ 41 | uint8_t csrcLen:4; 42 | uint8_t extension:1; 43 | uint8_t padding:1; 44 | uint8_t version:2; 45 | 46 | /* byte 1 */ 47 | uint8_t payloadType:7; 48 | uint8_t marker:1; 49 | 50 | /* bytes 2,3 */ 51 | uint16_t seq; 52 | 53 | /* bytes 4-7 */ 54 | uint32_t timestamp; 55 | 56 | /* bytes 8-11 */ 57 | uint32_t ssrc; 58 | 59 | /* data */ 60 | uint8_t payload[0]; 61 | }; 62 | 63 | class RtpPacket 64 | { 65 | public: 66 | RtpPacket() : 67 | _mBuffer(new uint8_t[RTP_MAX_PKT_SIZE+RTP_HEADER_SIZE+100]), 68 | mBuffer(_mBuffer+4), 69 | mRtpHeadr((RtpHeader*)mBuffer), 70 | mSize(0) 71 | { 72 | 73 | } 74 | 75 | ~RtpPacket() 76 | { 77 | delete _mBuffer; 78 | } 79 | 80 | uint8_t* _mBuffer; 81 | uint8_t* mBuffer; 82 | RtpHeader* const mRtpHeadr; 83 | int mSize; 84 | }; 85 | 86 | #endif //_RTP_H_ -------------------------------------------------------------------------------- /src/rtsp/RtpInstance.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _RTPINSTANNCE_H_ 26 | #define _RTPINSTANNCE_H_ 27 | #include 28 | #include 29 | #include 30 | 31 | #include "Ipv4Address.h" 32 | #include "SocketOptions.h" 33 | #include "Rtp.h" 34 | 35 | class RtpInstance 36 | { 37 | public: 38 | enum RtpType 39 | { 40 | RTP_OVER_UDP, 41 | RTP_OVER_TCP 42 | }; 43 | 44 | static RtpInstance* createNewOverUdp(int localSockfd, uint16_t localPort, 45 | std::string destIp, uint16_t destPort) 46 | { 47 | return new RtpInstance(localSockfd, localPort, destIp, destPort); 48 | } 49 | 50 | static RtpInstance* createNewOverTcp(int clientSockfd, uint8_t rtpChannel) 51 | { 52 | return new RtpInstance(clientSockfd, rtpChannel); 53 | } 54 | 55 | ~RtpInstance() 56 | { 57 | SocketOptions::close(mServerSockfd); 58 | } 59 | 60 | uint16_t getLocalPort() const { return mServerPort; } 61 | uint16_t getPeerPort() { return mClientAddr.getPort(); } 62 | 63 | int send(RtpPacket* rtpPacket) 64 | { 65 | if(mRtpType == RTP_OVER_UDP) 66 | { 67 | return sendOverUdp(rtpPacket->mBuffer, rtpPacket->mSize); 68 | } 69 | else 70 | { 71 | uint8_t* rtpPktPtr = rtpPacket->_mBuffer; 72 | rtpPktPtr[0] = '$'; 73 | rtpPktPtr[1] = (uint8_t)mRtpChannel; 74 | rtpPktPtr[2] = (uint8_t)(((rtpPacket->mSize)&0xFF00)>>8); 75 | rtpPktPtr[3] = (uint8_t)((rtpPacket->mSize)&0xFF); 76 | return sendOverTcp(rtpPktPtr, rtpPacket->mSize+4); 77 | } 78 | } 79 | 80 | bool alive() const { 81 | return mIsAlive; 82 | } 83 | int setAlive(bool alive) { mIsAlive = alive; }; 84 | void setSessionId(uint16_t sessionId) { mSessionId = sessionId; } 85 | uint16_t getSessionId() const { return mSessionId; } 86 | 87 | public: 88 | RtpInstance(int localSockfd, uint16_t localPort, const std::string& destIp, uint16_t destPort) : 89 | mRtpType(RTP_OVER_UDP), mServerSockfd(localSockfd), mServerPort(localPort), 90 | mClientAddr(destIp, destPort), mIsAlive(false), mSessionId(0) 91 | { 92 | 93 | } 94 | 95 | RtpInstance(int clientSockfd, uint8_t rtpChannel) : 96 | mRtpType(RTP_OVER_TCP), mServerSockfd(clientSockfd), 97 | mIsAlive(false), mSessionId(0), mRtpChannel(rtpChannel) 98 | { 99 | 100 | } 101 | private: 102 | int sendOverUdp(void* buf, int size) 103 | { 104 | return SocketOptions::sendto(mServerSockfd, buf, size, mClientAddr.getAddr()); 105 | } 106 | 107 | int sendOverTcp(void* buf, int size) 108 | { 109 | return SocketOptions::write(mServerSockfd, buf, size); 110 | } 111 | 112 | 113 | private: 114 | RtpType mRtpType; 115 | int mServerSockfd; 116 | uint16_t mServerPort; //for udp 117 | Ipv4Address mClientAddr; //for udp 118 | bool mIsAlive; 119 | uint16_t mSessionId; 120 | uint8_t mRtpChannel; //for tcp 121 | }; 122 | 123 | #endif //_RTPINSTANNCE_H_ -------------------------------------------------------------------------------- /src/rtsp/RtpSink.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include "RtpSink.h" 27 | #include "Mylog.h" 28 | RtpSink::RtpSink(Env* env,MediaSource* mediaSource, int payloadType) : 29 | mMediaSource(mediaSource), 30 | mSendPacketCallback(NULL), 31 | mCsrcLen(0), 32 | mExtension(0), 33 | mPadding(0), 34 | mVersion(RTP_VESION), 35 | mPayloadType(payloadType), 36 | mMarker(0), 37 | mSeq(0), 38 | mTimestamp(0), 39 | mEnv(env) 40 | 41 | { 42 | uint32_t frameTime = 1000/(mMediaSource->getFps()); 43 | mEnv->addTimer(timeoutCallback,frameTime,true,this); 44 | mSSRC = rand(); 45 | } 46 | 47 | RtpSink::~RtpSink() 48 | { 49 | delete mTimerEvent; 50 | } 51 | 52 | void RtpSink::setSendFrameCallback(SendPacketCallback cb, void* arg1, void* arg2) 53 | { 54 | mSendPacketCallback = cb; 55 | mArg1 = arg1; 56 | mArg2 = arg2; 57 | } 58 | 59 | void RtpSink::sendRtpPacket(RtpPacket* packet) 60 | { 61 | RtpHeader* rtpHead = packet->mRtpHeadr; 62 | rtpHead->csrcLen = mCsrcLen; 63 | rtpHead->extension = mExtension; 64 | rtpHead->padding = mPadding; 65 | rtpHead->version = mVersion; 66 | rtpHead->payloadType = mPayloadType; 67 | rtpHead->marker = mMarker; 68 | rtpHead->seq = htons(mSeq); 69 | rtpHead->timestamp = htonl(mTimestamp); 70 | rtpHead->ssrc = htonl(mSSRC); 71 | packet->mSize += RTP_HEADER_SIZE; 72 | 73 | if(mSendPacketCallback) 74 | mSendPacketCallback(mArg1, mArg2, packet); 75 | } 76 | 77 | void RtpSink::timeoutCallback(void* arg) 78 | { 79 | RtpSink* rtpSink = (RtpSink*)arg; 80 | AVFrame* frame = rtpSink->mMediaSource->getFrame(); 81 | if(!frame) 82 | { 83 | LOGI("get frame was NULL\n"); 84 | return; 85 | } 86 | 87 | rtpSink->handleFrame(frame); 88 | 89 | rtpSink->mMediaSource->putFrame(frame); 90 | 91 | } 92 | 93 | void RtpSink::start(int ms) 94 | { 95 | //mTimerEvent->setTimeout((uint32_t)ms); 96 | mTimerEvent->start(ms*1000,true); 97 | } 98 | 99 | void RtpSink::stop() 100 | { 101 | //mEnv->scheduler()->removeTimedEvent(mTimerId); 102 | } -------------------------------------------------------------------------------- /src/rtsp/RtpSink.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _MEDIA_SINK_H_ 26 | #define _MEDIA_SINK_H_ 27 | #include 28 | #include 29 | 30 | #include "MediaSource.h" 31 | #include "Rtp.h" 32 | #include "Event.h" 33 | #include "TimeEventManager.h" 34 | #include "Env.h" 35 | 36 | class RtpSink 37 | { 38 | public: 39 | typedef void (*SendPacketCallback)(void* arg1, void* arg2, RtpPacket* mediaPacket); 40 | 41 | RtpSink(Env* env,MediaSource* mediaSource, int payloadType); 42 | virtual ~RtpSink(); 43 | 44 | virtual std::string getMediaDescription(uint16_t port) = 0; 45 | virtual std::string getAttribute() = 0; 46 | 47 | void setSendFrameCallback(SendPacketCallback cb, void* arg1, void* arg2); 48 | 49 | protected: 50 | virtual void handleFrame(AVFrame* frame) = 0; 51 | void sendRtpPacket(RtpPacket* packet); 52 | void start(int ms); 53 | void stop(); 54 | 55 | private: 56 | static void timeoutCallback(void*); 57 | 58 | protected: 59 | MediaSource* mMediaSource; 60 | SendPacketCallback mSendPacketCallback; 61 | void* mArg1; 62 | void* mArg2; 63 | 64 | uint8_t mCsrcLen; 65 | uint8_t mExtension; 66 | uint8_t mPadding; 67 | uint8_t mVersion; 68 | uint8_t mPayloadType; 69 | uint8_t mMarker; 70 | uint16_t mSeq; 71 | uint32_t mTimestamp; 72 | uint32_t mSSRC; 73 | 74 | private: 75 | //TimerEvent* mTimerEvent; 76 | TimeEventManager* mTimerEvent; 77 | //Timer::TimerId mTimerId; 78 | Env* mEnv; 79 | }; 80 | 81 | #endif //_MEDIA_SINK_H_ -------------------------------------------------------------------------------- /src/rtsp/RtspConnection.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "RtspConnection.h" 32 | #include "MediaSession.h" 33 | #include "Mylog.h" 34 | 35 | void RtspConnection::getSocketIp(int sockfd, std::string& ip) 36 | { 37 | struct sockaddr_in addr; 38 | socklen_t addrlen = sizeof(struct sockaddr_in); 39 | getpeername(sockfd, (struct sockaddr*)&addr, &addrlen); 40 | ip = inet_ntoa(addr.sin_addr); 41 | LOGI("The peer IP: %s \n",ip.c_str()); 42 | } 43 | 44 | RtspConnection* RtspConnection::createNew(RtspServer* rtspServer, int sockfd) 45 | { 46 | return new RtspConnection(rtspServer, sockfd); 47 | } 48 | 49 | RtspConnection::RtspConnection(RtspServer* rtspServer, int sockfd) : 50 | TcpConnect(sockfd), 51 | mRtspServer(rtspServer), 52 | mMethod(NONE), 53 | mTrackId(MediaSession::TrackIdNone), 54 | mSessionId(rand()), 55 | mIsRtpOverTcp(false) 56 | { 57 | for(int i = 0; i < MEDIA_MAX_TRACK_NUM; ++i) 58 | { 59 | mRtpInstances[i] = NULL; 60 | mRtcpInstances[i] = NULL; 61 | } 62 | 63 | getSocketIp(sockfd, mPeerIp); 64 | } 65 | 66 | RtspConnection::~RtspConnection() 67 | { 68 | for(int i = 0; i < MEDIA_MAX_TRACK_NUM; ++i) 69 | { 70 | if(mRtpInstances[i]) 71 | { 72 | if(mSession){ 73 | mSession->removeRtpInstance(mRtpInstances[i]); 74 | } 75 | delete mRtpInstances[i]; 76 | mRtpInstances[i] = NULL; 77 | } 78 | 79 | if(mRtcpInstances[i]) 80 | { 81 | delete mRtcpInstances[i]; 82 | mRtcpInstances[i] = NULL; 83 | } 84 | } 85 | } 86 | 87 | void RtspConnection::handleReadBytes() 88 | { 89 | LOGI("RTSPconnection read handle\n"); 90 | bool ret; 91 | 92 | if(mIsRtpOverTcp) 93 | { 94 | if(mInputBuffer.getReadStart()[0] == '$') 95 | { 96 | handleRtpOverTcp(); 97 | return; 98 | } 99 | } 100 | 101 | ret = parseRequest(); 102 | if(ret != true) 103 | { 104 | LOGI("failed to parse request\n"); 105 | goto err; 106 | } 107 | 108 | switch (mMethod) 109 | { 110 | case OPTIONS: 111 | LOGI("handle OPTIONS cmd\n"); 112 | if(handleCmdOption() != true){ 113 | goto err; 114 | } 115 | LOGI("handle OPTIONS cmd successful\n"); 116 | break; 117 | case DESCRIBE: 118 | LOGI("handle DESCRIBE cmd\n"); 119 | if(handleCmdDescribe() != true){ 120 | goto err; 121 | } 122 | 123 | LOGI("handle DESCRIBE cmd successful\n"); 124 | break; 125 | case SETUP: 126 | LOGI("handle SETUP cmd\n"); 127 | if(handleCmdSetup() != true){ 128 | goto err; 129 | } 130 | LOGI("handle SETUP cmd successful\n"); 131 | break; 132 | case PLAY: 133 | LOGI("handle PLAY cmd\n"); 134 | if(handleCmdPlay() != true){ 135 | goto err; 136 | } 137 | LOGI("handle PLAY cmd successful\n"); 138 | break; 139 | case TEARDOWN: 140 | LOGI("handle TEARDOWN cmd\n"); 141 | if(handleCmdTeardown() != true){ 142 | goto err; 143 | } 144 | LOGI("handle TEARDOWN cmd successful\n"); 145 | break; 146 | case GET_PARAMETER: 147 | LOGI("handle GET_PARAMETER cmd\n"); 148 | if(handleCmdGetParamter() != true) 149 | goto err; 150 | break; 151 | default: 152 | goto err; 153 | break; 154 | } 155 | 156 | return; 157 | err: 158 | handleDisconnection(); 159 | } 160 | 161 | bool RtspConnection::parseRequest() 162 | { 163 | bool ret; 164 | 165 | /* 解析第一行 */ 166 | const char* crlf = mInputBuffer.lookupCRLF(); 167 | if(crlf == NULL) 168 | { 169 | mInputBuffer.retrieveAll(); 170 | return false; 171 | } 172 | ret = parseRequest1(mInputBuffer.getReadStart(), crlf); 173 | if(ret == false) 174 | { 175 | LOGI("parseRequest1 for get metod erro\n"); 176 | mInputBuffer.retrieveAll(); 177 | return false; 178 | } 179 | mInputBuffer.retrieveUntil(crlf+2); 180 | 181 | /* 解析剩下的内容 */ 182 | crlf = mInputBuffer.findLastCrlf(); 183 | if(crlf == NULL) 184 | { 185 | mInputBuffer.retrieveAll(); 186 | return false; 187 | } 188 | ret = parseRequest2(mInputBuffer.getReadStart(), crlf); 189 | if(ret == false) 190 | { 191 | mInputBuffer.retrieveAll(); 192 | return false; 193 | } 194 | mInputBuffer.retrieveUntil(crlf + 2); 195 | 196 | return true; 197 | } 198 | //get Method 199 | bool RtspConnection::parseRequest1(const char* begin, const char* end) 200 | { 201 | std::string message(begin, end); 202 | char method[64] = {0}; 203 | char url[512] = {0}; 204 | char version[64] = {0}; 205 | 206 | if(sscanf(message.c_str(), "%s %s %s", method, url, version) != 3) 207 | { 208 | return false; 209 | } 210 | if(!strcmp(method, "OPTIONS")) 211 | mMethod = OPTIONS; 212 | else if(!strcmp(method, "DESCRIBE")) 213 | mMethod = DESCRIBE; 214 | else if(!strcmp(method, "SETUP")) 215 | mMethod = SETUP; 216 | else if(!strcmp(method, "PLAY")) 217 | mMethod = PLAY; 218 | else if(!strcmp(method, "TEARDOWN")) 219 | mMethod = TEARDOWN; 220 | else if(!strcmp(method, "GET_PARAMETER")) 221 | mMethod = GET_PARAMETER; 222 | else 223 | { 224 | mMethod = NONE; 225 | return false; 226 | } 227 | if(strncmp(url, "rtsp://", 7) != 0) 228 | { 229 | return false; 230 | } 231 | uint16_t port = 0; 232 | char ip[64] = {0}; 233 | char name[64] = {0}; 234 | int ret = sscanf(url+7, "%[^:]:%hu/%s", ip, &port, name); 235 | if(ret ==2 || ret ==3){ 236 | LOGI("parse url IP:%s \n Port:%d\n Name:%s\n",ip,port,name); 237 | } 238 | else if(sscanf(url+7, "%[^/]/%s", ip, name) == 2) 239 | { 240 | port = 554; 241 | } 242 | else 243 | { 244 | return false; 245 | } 246 | mUrl = url; 247 | mSuffix = name; 248 | return true; 249 | } 250 | 251 | bool RtspConnection::parseCSeq(std::string& message) 252 | { 253 | std::size_t pos = message.find("CSeq"); 254 | if (pos != std::string::npos) 255 | { 256 | uint32_t cseq = 0; 257 | sscanf(message.c_str()+pos, "%*[^:]: %u", &cseq); 258 | mCSeq = cseq; 259 | return true; 260 | } 261 | 262 | return false; 263 | } 264 | 265 | bool RtspConnection::parseAccept(std::string& message) 266 | { 267 | if ((message.rfind("Accept")==std::string::npos) 268 | || (message.rfind("sdp")==std::string::npos)) 269 | { 270 | return false; 271 | } 272 | 273 | return true; 274 | } 275 | 276 | bool RtspConnection::parseTransport(std::string& message) 277 | { 278 | std::size_t pos = message.find("Transport"); 279 | if(pos != std::string::npos) 280 | { 281 | if((pos=message.find("RTP/AVP/TCP")) != std::string::npos) 282 | { 283 | uint8_t rtpChannel, rtcpChannel; 284 | mIsRtpOverTcp = true; 285 | 286 | if(sscanf(message.c_str()+pos, "%*[^;];%*[^;];%*[^=]=%hhu-%hhu", 287 | &rtpChannel, &rtcpChannel) != 2) 288 | { 289 | return false; 290 | } 291 | 292 | mRtpChannel = rtpChannel; 293 | 294 | return true; 295 | } 296 | else if((pos=message.find("RTP/AVP")) != std::string::npos) 297 | { 298 | uint16_t rtpPort = 0, rtcpPort = 0; 299 | if(((message.find("unicast", pos)) != std::string::npos)) 300 | { 301 | if(sscanf(message.c_str()+pos, "%*[^;];%*[^;];%*[^=]=%hu-%hu", 302 | &rtpPort, &rtcpPort) != 2) 303 | { 304 | return false; 305 | } 306 | } 307 | else if((message.find("multicast", pos)) != std::string::npos) 308 | { 309 | return true; 310 | } 311 | else 312 | return false; 313 | 314 | mPeerRtpPort = rtpPort; 315 | mPeerRtcpPort = rtcpPort; 316 | LOGI("handle setup get client port: RTP:%d RTCP:%d\n",mPeerRtpPort,mPeerRtcpPort); 317 | } 318 | else 319 | { 320 | return false; 321 | } 322 | 323 | return true; 324 | } 325 | 326 | return false; 327 | } 328 | 329 | bool RtspConnection::parseMediaTrack() 330 | { 331 | std::size_t pos = mUrl.find("track0"); 332 | if(pos != std::string::npos) 333 | { 334 | mTrackId = MediaSession::TrackId0; 335 | LOGI("handle setup get client trackID:%d\n",mTrackId); 336 | return true; 337 | } 338 | 339 | pos = mUrl.find("track1"); 340 | if(pos != std::string::npos) 341 | { 342 | mTrackId = MediaSession::TrackId1; 343 | LOGI("handle setup get client trackID:%d\n",mTrackId); 344 | return true; 345 | } 346 | 347 | return false; 348 | } 349 | 350 | bool RtspConnection::parseSessionId(std::string& message) 351 | { 352 | std::size_t pos = message.find("Session"); 353 | if (pos != std::string::npos) 354 | { 355 | uint32_t sessionId = 0; 356 | if(sscanf(message.c_str()+pos, "%*[^:]: %u", &sessionId) != 1) 357 | return false; 358 | return true; 359 | } 360 | 361 | return false; 362 | } 363 | 364 | bool RtspConnection::parseRequest2(const char* begin, const char* end) 365 | { 366 | std::string message(begin, end); 367 | 368 | if(parseCSeq(message) != true){ 369 | LOGI("Parse CSeq erro!\n"); 370 | return false; 371 | } 372 | 373 | if(mMethod == OPTIONS){ 374 | return true; 375 | } 376 | if(mMethod == DESCRIBE){ 377 | return parseAccept(message); 378 | } 379 | 380 | if(mMethod == SETUP) 381 | { 382 | if(parseTransport(message) != true){ 383 | return false; 384 | } 385 | return parseMediaTrack(); 386 | } 387 | 388 | if(mMethod == PLAY){ 389 | return parseSessionId(message); 390 | } 391 | if(mMethod == TEARDOWN){ 392 | return true; 393 | } 394 | if(mMethod == GET_PARAMETER){ 395 | return true; 396 | } 397 | return false; 398 | } 399 | 400 | bool RtspConnection::handleCmdOption() 401 | { 402 | snprintf(mBuffer, sizeof(mBuffer), 403 | "RTSP/1.0 200 OK\r\n" 404 | "CSeq: %u\r\n" 405 | "Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY\r\n" 406 | "\r\n", mCSeq); 407 | 408 | if(sendMessage(mBuffer, strlen(mBuffer)) < 0) 409 | return false; 410 | 411 | return true; 412 | } 413 | 414 | bool RtspConnection::handleCmdDescribe() 415 | { 416 | MediaSession* session = mRtspServer->loopupMediaSession(mSuffix); 417 | if(!session) 418 | { 419 | LOGI("can't loop up %s session\n", mSuffix.c_str()); 420 | return false; 421 | } 422 | 423 | mSession = session; 424 | std::string sdp = session->generateSDPDescription(); 425 | 426 | memset((void*)mBuffer, 0, sizeof(mBuffer)); 427 | snprintf((char*)mBuffer, sizeof(mBuffer), 428 | "RTSP/1.0 200 OK\r\n" 429 | "CSeq: %u\r\n" 430 | "Content-Length: %u\r\n" 431 | "Content-Type: application/sdp\r\n" 432 | "\r\n" 433 | "%s", 434 | mCSeq, 435 | (unsigned int)sdp.size(), 436 | sdp.c_str()); 437 | 438 | if(sendMessage(mBuffer, strlen(mBuffer)) < 0) 439 | return false; 440 | 441 | return true; 442 | } 443 | 444 | bool RtspConnection::handleCmdSetup() 445 | { 446 | char sessionName[100]; 447 | if(sscanf(mSuffix.c_str(), "%[^/]/", sessionName) != 1) 448 | { 449 | return false; 450 | } 451 | 452 | MediaSession* session = mRtspServer->loopupMediaSession(sessionName); 453 | if(!session) 454 | { 455 | LOGI("can't loop up %s session\n", sessionName); 456 | return false; 457 | } 458 | 459 | if(mTrackId >= MEDIA_MAX_TRACK_NUM || mRtpInstances[mTrackId] || mRtcpInstances[mTrackId]){ 460 | LOGI("The track is can not be used!\n"); 461 | return false; 462 | } 463 | 464 | 465 | if(session->isStartMulticast()) 466 | { 467 | LOGI("Transport ovet Multicast\n"); 468 | snprintf((char*)mBuffer, sizeof(mBuffer), 469 | "RTSP/1.0 200 OK\r\n" 470 | "CSeq: %d\r\n" 471 | "Transport: RTP/AVP;multicast;" 472 | "destination=%s;source=%s;port=%d-%d;ttl=255\r\n" 473 | "Session: %08x\r\n" 474 | "\r\n", 475 | mCSeq, 476 | session->getMulticastDestAddr().c_str(), 477 | SocketOptions::getLocalIp().c_str(), 478 | session->getMulticastDestRtpPort(mTrackId), 479 | session->getMulticastDestRtpPort(mTrackId)+1, 480 | mSessionId); 481 | } 482 | else 483 | { 484 | if(mIsRtpOverTcp) //rtp over tcp 485 | { 486 | /* setup rtp over tcp */ 487 | LOGI("Transport ovet TCP\n"); 488 | createRtpOverTcp(mTrackId, mSocket.getSocketFd(), mRtpChannel); 489 | mRtpInstances[mTrackId]->setSessionId(mSessionId); 490 | session->addRtpInstance(mTrackId, mRtpInstances[mTrackId]); 491 | 492 | snprintf((char*)mBuffer, sizeof(mBuffer), 493 | "RTSP/1.0 200 OK\r\n" 494 | "CSeq: %d\r\n" 495 | "Transport: RTP/AVP/TCP;unicast;interleaved=%hhu-%hhu\r\n" 496 | "Session: %08x\r\n" 497 | "\r\n", 498 | mCSeq, 499 | mRtpChannel, 500 | mRtpChannel+1, 501 | mSessionId); 502 | } 503 | else //rtp over udp 504 | { 505 | LOGI("Transport ovet UDP\n"); 506 | if(createRtpRtcpOverUdp(mTrackId, mPeerIp, mPeerRtpPort, mPeerRtcpPort) != true) 507 | { 508 | LOGI("failed to create rtp and rtcp\n"); 509 | return false; 510 | } 511 | 512 | mRtpInstances[mTrackId]->setSessionId(mSessionId); 513 | mRtcpInstances[mTrackId]->setSessionId(mSessionId); 514 | 515 | /* add to sesion */ 516 | session->addRtpInstance(mTrackId, mRtpInstances[mTrackId]); 517 | 518 | snprintf((char*)mBuffer, sizeof(mBuffer), 519 | "RTSP/1.0 200 OK\r\n" 520 | "CSeq: %u\r\n" 521 | "Transport: RTP/AVP;unicast;client_port=%hu-%hu;server_port=%hu-%hu\r\n" 522 | "Session: %08x\r\n" 523 | "\r\n", 524 | mCSeq, 525 | mPeerRtpPort, 526 | mPeerRtcpPort, 527 | mRtpInstances[mTrackId]->getLocalPort(), 528 | mRtcpInstances[mTrackId]->getLocalPort(), 529 | mSessionId); 530 | } 531 | 532 | } 533 | 534 | if(sendMessage(mBuffer, strlen(mBuffer)) < 0){ 535 | return false; 536 | } 537 | LOGI("send msg to client:\n%s\n",mBuffer); 538 | return true; 539 | } 540 | 541 | bool RtspConnection::handleCmdPlay() 542 | { 543 | snprintf((char*)mBuffer, sizeof(mBuffer), 544 | "RTSP/1.0 200 OK\r\n" 545 | "CSeq: %d\r\n" 546 | "Range: npt=0.000-\r\n" 547 | "Session: %08x; timeout=60\r\n" 548 | "\r\n", 549 | mCSeq, 550 | mSessionId); 551 | if(sendMessage(mBuffer, strlen(mBuffer)) < 0){ 552 | LOGI("failed to send respon to play%n"); 553 | return false; 554 | } 555 | LOGI("Play send data:\n%s",mBuffer); 556 | for(int i = 0; i < MEDIA_MAX_TRACK_NUM; ++i) 557 | { 558 | if(mRtpInstances[i]) 559 | mRtpInstances[i]->setAlive(true); 560 | 561 | if(mRtcpInstances[i]) 562 | mRtcpInstances[i]->setAlive(true); 563 | } 564 | return true; 565 | } 566 | 567 | bool RtspConnection::handleCmdTeardown() 568 | { 569 | snprintf((char*)mBuffer, sizeof(mBuffer), 570 | "RTSP/1.0 200 OK\r\n" 571 | "CSeq: %d\r\n" 572 | "\r\n", 573 | mCSeq); 574 | 575 | if(sendMessage(mBuffer, strlen(mBuffer)) < 0) 576 | { 577 | return false; 578 | } 579 | 580 | return true; 581 | } 582 | 583 | bool RtspConnection::handleCmdGetParamter() 584 | { 585 | 586 | } 587 | 588 | int RtspConnection::sendMessage(void* buf, int size) 589 | { 590 | int ret; 591 | 592 | mOutBuffer.append(buf, size); 593 | ret = mOutBuffer.write(mSocket.getSocketFd()); 594 | mOutBuffer.retrieveAll(); 595 | 596 | return ret; 597 | } 598 | 599 | int RtspConnection::sendMessage() 600 | { 601 | int ret; 602 | 603 | ret = mOutBuffer.write(mSocket.getSocketFd()); 604 | mOutBuffer.retrieveAll(); 605 | 606 | return ret; 607 | } 608 | 609 | bool RtspConnection::createRtpRtcpOverUdp(MediaSession::TrackId trackId, std::string peerIp, 610 | uint16_t peerRtpPort, uint16_t peerRtcpPort) 611 | { 612 | int rtpSockfd, rtcpSockfd; 613 | int16_t rtpPort, rtcpPort; 614 | bool ret; 615 | 616 | if(mRtpInstances[trackId] || mRtcpInstances[trackId]) 617 | return false; 618 | 619 | int i; 620 | for(i = 0; i < 10; ++i) 621 | { 622 | rtpSockfd = SocketOptions::createUdpSocket(); 623 | if(rtpSockfd < 0) 624 | { 625 | return false; 626 | } 627 | 628 | rtcpSockfd = SocketOptions::createUdpSocket(); 629 | if(rtcpSockfd < 0) 630 | { 631 | close(rtpSockfd); 632 | return false; 633 | } 634 | 635 | uint16_t port = rand() & 0xfffe; 636 | if(port < 10000) 637 | port += 10000; 638 | 639 | rtpPort = port; 640 | rtcpPort = port+1; 641 | 642 | ret = SocketOptions::bind(rtpSockfd, "0.0.0.0", rtpPort); 643 | if(ret != true) 644 | { 645 | SocketOptions::close(rtpSockfd); 646 | SocketOptions::close(rtcpSockfd); 647 | continue; 648 | } 649 | 650 | ret = SocketOptions::bind(rtcpSockfd, "0.0.0.0", rtcpPort); 651 | if(ret != true) 652 | { 653 | SocketOptions::close(rtpSockfd); 654 | SocketOptions::close(rtcpSockfd); 655 | continue; 656 | } 657 | 658 | break; 659 | } 660 | 661 | if(i == 10) 662 | return false; 663 | 664 | mRtpInstances[trackId] = RtpInstance::createNewOverUdp(rtpSockfd, rtpPort, 665 | peerIp, peerRtpPort); 666 | mRtcpInstances[trackId] = RtcpInstance::createNew(rtcpSockfd, rtcpPort, 667 | peerIp, peerRtcpPort); 668 | 669 | return true; 670 | } 671 | 672 | bool RtspConnection::createRtpOverTcp(MediaSession::TrackId trackId, int sockfd, 673 | uint8_t rtpChannel) 674 | { 675 | mRtpInstances[trackId] = RtpInstance::createNewOverTcp(sockfd, rtpChannel); 676 | 677 | return true; 678 | } 679 | 680 | void RtspConnection::handleRtpOverTcp() 681 | { 682 | uint8_t* buf = (uint8_t*)mInputBuffer.getReadStart(); 683 | uint16_t size; 684 | 685 | size = (buf[2]<<8) | buf[3]; 686 | if(mInputBuffer.readableDataSize() < size+4) 687 | return; 688 | 689 | mInputBuffer.retrieve(size+4); 690 | } -------------------------------------------------------------------------------- /src/rtsp/RtspConnection.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _RTSP_CONNECTION__ 26 | #define _RTSP_CONNECTION__ 27 | #include 28 | 29 | #include "TcpConnect.h" 30 | #include "RtspServer.h" 31 | #include "RtpInstance.h" 32 | #include "MediaSession.h" 33 | #include "Event.h" 34 | 35 | class RtspServer; 36 | class RtspConnection : public TcpConnect 37 | { 38 | public: 39 | /* 40 | *The Rtspserver command 41 | */ 42 | enum Method 43 | { 44 | OPTIONS, DESCRIBE, SETUP, PLAY, TEARDOWN, GET_PARAMETER, RTCP, 45 | NONE, 46 | }; 47 | static void getSocketIp(int sockfd, std::string& ip); 48 | static RtspConnection* createNew(RtspServer* rtspServer, int sockfd); 49 | 50 | RtspConnection(RtspServer* rtspServer, int sockfd); 51 | ~RtspConnection(); 52 | 53 | protected: 54 | virtual void handleReadBytes(); 55 | 56 | private: 57 | bool parseRequest(); 58 | bool parseRequest1(const char* begin, const char* end); 59 | bool parseRequest2(const char* begin, const char* end); 60 | 61 | bool parseCSeq(std::string& message); 62 | bool parseAccept(std::string& message); 63 | bool parseTransport(std::string& message); 64 | bool parseMediaTrack(); 65 | bool parseSessionId(std::string& message); 66 | 67 | bool handleCmdOption(); 68 | bool handleCmdDescribe(); 69 | bool handleCmdSetup(); 70 | bool handleCmdPlay(); 71 | bool handleCmdTeardown(); 72 | bool handleCmdGetParamter(); 73 | 74 | int sendMessage(void* buf, int size); 75 | int sendMessage(); 76 | 77 | bool createRtpRtcpOverUdp(MediaSession::TrackId trackId, std::string peerIp, 78 | uint16_t peerRtpPort, uint16_t peerRtcpPort); 79 | bool createRtpOverTcp(MediaSession::TrackId trackId, int sockfd, uint8_t rtpChannel); 80 | 81 | void handleRtpOverTcp(); 82 | 83 | private: 84 | RtspServer* mRtspServer; 85 | std::string mPeerIp; 86 | Method mMethod; 87 | std::string mUrl; 88 | std::string mSuffix; 89 | uint32_t mCSeq; 90 | uint16_t mPeerRtpPort; 91 | uint16_t mPeerRtcpPort; 92 | MediaSession::TrackId mTrackId; 93 | RtpInstance* mRtpInstances[MEDIA_MAX_TRACK_NUM]; 94 | RtcpInstance* mRtcpInstances[MEDIA_MAX_TRACK_NUM]; 95 | MediaSession* mSession; 96 | int mSessionId; 97 | bool mIsRtpOverTcp; 98 | uint8_t mRtpChannel; 99 | }; 100 | 101 | 102 | #endif -------------------------------------------------------------------------------- /src/rtsp/RtspServer.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include "RtspServer.h" 26 | #include "Mylog.h" 27 | 28 | RtspServer* RtspServer::createNew(Env* env, Ipv4Address& addr) 29 | { 30 | return new RtspServer(env,addr); 31 | } 32 | 33 | RtspServer::RtspServer(Env* env,const Ipv4Address& addr):TcpServer(env,addr) 34 | { 35 | mTriggerEvent = TriggerEvent::createNew(this); 36 | mTriggerEvent->setTriggerCallback(triggerCallback); 37 | } 38 | 39 | RtspServer::~RtspServer(){ 40 | 41 | } 42 | bool RtspServer::addMeidaSession(MediaSession* mediaSession) 43 | { 44 | if(mMediaSessions.find(mediaSession->name()) != mMediaSessions.end()){ 45 | return false; 46 | } 47 | mMediaSessions.insert(std::make_pair(mediaSession->name(), mediaSession)); 48 | return true; 49 | } 50 | 51 | void RtspServer::handleNewConnection(ClientInfo* clientinfo){ 52 | LOGI("New client connet\n"); 53 | LOGI("client IP:  %s \n",clientinfo->clientIp); 54 | LOGI("client port: %d \n",clientinfo->clientPort); 55 | LOGI("client fd : %d \n",clientinfo->clientSockfd); 56 | RtspConnection* conn = RtspConnection::createNew(this, clientinfo->clientSockfd); 57 | conn->setDisconnectionCallback(disconnectionCallback, this); 58 | mConnections.insert(std::make_pair(clientinfo->clientSockfd, conn)); 59 | return; 60 | } 61 | void RtspServer::disconnectionCallback(void* arg, int sockfd){ 62 | LOGI("A call disconnect \n"); 63 | } 64 | 65 | MediaSession* RtspServer::loopupMediaSession(std::string name) 66 | { 67 | std::map::iterator it = mMediaSessions.find(name); 68 | if(it == mMediaSessions.end()){ 69 | return NULL; 70 | } 71 | return it->second; 72 | } 73 | void RtspServer::triggerCallback(void* arg) 74 | { 75 | RtspServer* rtspServer = (RtspServer*)arg; 76 | rtspServer->handleDisconnectionList(); 77 | } 78 | 79 | std::string RtspServer::getUrl(MediaSession* session) 80 | { 81 | char url[200]; 82 | 83 | snprintf(url, sizeof(url), "rtsp://%s:%d/%s", SocketOptions::getLocalIp().c_str(), 84 | mAddr.getPort(), session->name().c_str()); 85 | 86 | return std::string(url); 87 | } 88 | 89 | void RtspServer::handleDisconnectionList() 90 | { 91 | //上所 92 | for(std::vector::iterator it = mDisconnectionlist.begin(); it != mDisconnectionlist.end(); ++it) 93 | { 94 | int sockfd = *it; 95 | std::map::iterator _it = mConnections.find(sockfd); 96 | assert(_it != mConnections.end()); 97 | delete _it->second; 98 | mConnections.erase(sockfd); 99 | } 100 | mDisconnectionlist.clear(); 101 | } -------------------------------------------------------------------------------- /src/rtsp/RtspServer.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _RTSPSERVER__H 26 | #define _RTSPSERVER__H 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "TcpServer.h" 34 | #include "RtspConnection.h" 35 | #include "MediaSession.h" 36 | #include "Event.h" 37 | #include "Env.h" 38 | class RtspConnection; 39 | 40 | class RtspServer :public TcpServer 41 | { 42 | public: 43 | static RtspServer* createNew(Env* env,Ipv4Address& addr); 44 | 45 | RtspServer(Env* env,const Ipv4Address& addr); 46 | virtual ~RtspServer(); 47 | 48 | bool addMeidaSession(MediaSession* mediaSession); 49 | void handleNewConnection(int connfd); 50 | MediaSession* loopupMediaSession(std::string name); 51 | std::string getUrl(MediaSession* session); 52 | 53 | protected: 54 | virtual void handleNewConnection(ClientInfo* clientinfo); 55 | static void disconnectionCallback(void* arg, int sockfd); 56 | void handleDisconnection(int sockfd); 57 | static void triggerCallback(void*); 58 | void handleDisconnectionList(); 59 | 60 | private: 61 | std::map mConnections; 62 | std::map mMediaSessions; 63 | std::vector mDisconnectionlist; 64 | TriggerEvent* mTriggerEvent; 65 | 66 | }; 67 | 68 | #endif -------------------------------------------------------------------------------- /src/rtsp/SocketOptions.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "SocketOptions.h" 37 | #include "Mylog.h" 38 | 39 | int SocketOptions::createTcpSocket() 40 | { 41 | int sockfd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP); 42 | if(sockfd < 0){ 43 | return -1; 44 | } 45 | return sockfd; 46 | } 47 | 48 | int SocketOptions::createUdpSocket() 49 | { 50 | int sockfd = ::socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); 51 | 52 | return sockfd; 53 | } 54 | 55 | bool SocketOptions::bind(int sockfd, std::string ip, uint16_t port) 56 | { 57 | struct sockaddr_in addr = {0}; 58 | addr.sin_family = AF_INET; 59 | //addr.sin_addr.s_addr = inet_addr(ip.c_str()); 60 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 61 | addr.sin_port = htons(port); 62 | 63 | if(::bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) 64 | { 65 | LOGI("bind Failed\n"); 66 | return false; 67 | } 68 | 69 | return true; 70 | } 71 | 72 | bool SocketOptions::listen(int sockfd, int backlog) 73 | { 74 | if(::listen(sockfd, backlog) < 0){ 75 | LOGI("failed to listen\n"); 76 | return false; 77 | } 78 | return true; 79 | } 80 | 81 | int SocketOptions::accept(int sockfd) 82 | { 83 | struct sockaddr_in addr = { 0 }; 84 | socklen_t addrlen = sizeof(struct sockaddr_in); 85 | 86 | int connfd = ::accept(sockfd, (struct sockaddr*)&addr, &addrlen); 87 | setNonBlockAndCloseOnExec(connfd); 88 | ignoreSigPipeOnSocket(connfd); 89 | 90 | return connfd; 91 | } 92 | 93 | int SocketOptions::readv(int sockfd, const struct iovec *iov, int iovcnt) 94 | { 95 | return ::readv(sockfd, iov, iovcnt); 96 | } 97 | 98 | int SocketOptions::write(int sockfd, const void* buf, int size) 99 | { 100 | return ::write(sockfd, buf, size); 101 | } 102 | 103 | int SocketOptions::sendto(int sockfd, const void* buf, int len, 104 | const struct sockaddr *destAddr) 105 | { 106 | socklen_t addrLen = sizeof(struct sockaddr); 107 | return ::sendto(sockfd, buf, len, 0, destAddr, addrLen); 108 | } 109 | 110 | void SocketOptions::setNonBlock(int sockfd) 111 | { 112 | int flags = fcntl(sockfd, F_GETFL, 0); 113 | fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); 114 | } 115 | 116 | void SocketOptions::setBlock(int sockfd, int writeTimeout) 117 | { 118 | int flags = fcntl(sockfd, F_GETFL, 0); 119 | fcntl(sockfd, F_SETFL, flags&(~O_NONBLOCK)); 120 | 121 | if (writeTimeout > 0) 122 | { 123 | struct timeval tv = {writeTimeout/1000, (writeTimeout%1000)*1000}; 124 | setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv)); 125 | } 126 | } 127 | 128 | void SocketOptions::setReuseAddr(int sockfd, int on) 129 | { 130 | int optval = on ? 1 : 0; 131 | setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&optval, sizeof(optval)); 132 | } 133 | 134 | void SocketOptions::setReusePort(int sockfd) 135 | { 136 | #ifdef SO_REUSEPORT 137 | int on = 1; 138 | setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&on, sizeof(on)); 139 | #endif 140 | } 141 | 142 | void SocketOptions::setNonBlockAndCloseOnExec(int sockfd) 143 | { 144 | // non block,asynchronous 145 | int flags = ::fcntl(sockfd, F_GETFL, 0); 146 | flags |= O_NONBLOCK; 147 | int ret = ::fcntl(sockfd, F_SETFL, flags); 148 | 149 | // close on exec 150 | flags = ::fcntl(sockfd, F_GETFD, 0); 151 | flags |= FD_CLOEXEC; 152 | ret = ::fcntl(sockfd, F_SETFD, flags); 153 | } 154 | 155 | void SocketOptions::ignoreSigPipeOnSocket(int socketfd) 156 | { 157 | int option = 1; 158 | setsockopt(socketfd, SOL_SOCKET, MSG_NOSIGNAL, &option, sizeof(option)); 159 | } 160 | 161 | void SocketOptions::setNoDelay(int sockfd) 162 | { 163 | #ifdef TCP_NODELAY 164 | int on = 1; 165 | int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&on, sizeof(on)); 166 | #endif 167 | } 168 | 169 | void SocketOptions::setKeepAlive(int sockfd) 170 | { 171 | int on = 1; 172 | setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)); 173 | } 174 | 175 | void SocketOptions::setNoSigpipe(int sockfd) 176 | { 177 | #ifdef SO_NOSIGPIPE 178 | int on = 1; 179 | setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (char *)&on, sizeof(on)); 180 | #endif 181 | } 182 | 183 | void SocketOptions::setSendBufSize(int sockfd, int size) 184 | { 185 | setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(size)); 186 | } 187 | 188 | void SocketOptions::setRecvBufSize(int sockfd, int size) 189 | { 190 | setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size)); 191 | } 192 | 193 | std::string SocketOptions::getPeerIp(int sockfd) 194 | { 195 | struct sockaddr_in addr = { 0 }; 196 | socklen_t addrlen = sizeof(struct sockaddr_in); 197 | if (getpeername(sockfd, (struct sockaddr *)&addr, &addrlen) == 0) 198 | { 199 | return inet_ntoa(addr.sin_addr); 200 | } 201 | 202 | return "0.0.0.0"; 203 | } 204 | 205 | int16_t SocketOptions::getPeerPort(int sockfd) 206 | { 207 | struct sockaddr_in addr = { 0 }; 208 | socklen_t addrlen = sizeof(struct sockaddr_in); 209 | if (getpeername(sockfd, (struct sockaddr *)&addr, &addrlen) == 0) 210 | { 211 | return ntohs(addr.sin_port); 212 | } 213 | 214 | return 0; 215 | } 216 | 217 | int SocketOptions::getPeerAddr(int sockfd, struct sockaddr_in *addr) 218 | { 219 | socklen_t addrlen = sizeof(struct sockaddr_in); 220 | return getpeername(sockfd, (struct sockaddr *)addr, &addrlen); 221 | } 222 | 223 | void SocketOptions::close(int sockfd) 224 | { 225 | int ret = ::close(sockfd); 226 | } 227 | 228 | bool SocketOptions::connect(int sockfd, std::string ip, uint16_t port, int timeout) 229 | { 230 | bool isConnected = true; 231 | if (timeout > 0) 232 | { 233 | SocketOptions::setNonBlock(sockfd); 234 | } 235 | 236 | struct sockaddr_in addr = { 0 }; 237 | socklen_t addrlen = sizeof(addr); 238 | addr.sin_family = AF_INET; 239 | addr.sin_port = htons(port); 240 | addr.sin_addr.s_addr = inet_addr(ip.c_str()); 241 | if (::connect(sockfd, (struct sockaddr*)&addr, addrlen) < 0) 242 | { 243 | if (timeout > 0) 244 | { 245 | isConnected = false; 246 | fd_set fdWrite; 247 | FD_ZERO(&fdWrite); 248 | FD_SET(sockfd, &fdWrite); 249 | struct timeval tv = { timeout / 1000, timeout % 1000 * 1000 }; 250 | select(sockfd + 1, NULL, &fdWrite, NULL, &tv); 251 | if (FD_ISSET(sockfd, &fdWrite)) 252 | { 253 | isConnected = true; 254 | } 255 | SocketOptions::setBlock(sockfd, 0); 256 | } 257 | else 258 | { 259 | isConnected = false; 260 | } 261 | } 262 | 263 | return isConnected; 264 | } 265 | 266 | std::string SocketOptions::getLocalIp() 267 | { 268 | int sockfd = 0; 269 | char buf[512] = { 0 }; 270 | struct ifconf ifconf; 271 | struct ifreq *ifreq; 272 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); 273 | if (sockfd < 0) 274 | { 275 | close(sockfd); 276 | return "0.0.0.0"; 277 | } 278 | 279 | ifconf.ifc_len = 512; 280 | ifconf.ifc_buf = buf; 281 | if (ioctl(sockfd, SIOCGIFCONF, &ifconf) < 0) 282 | { 283 | close(sockfd); 284 | return "0.0.0.0"; 285 | } 286 | 287 | close(sockfd); 288 | 289 | ifreq = (struct ifreq*)ifconf.ifc_buf; 290 | for (int i = (ifconf.ifc_len / sizeof(struct ifreq)); i>0; i--) 291 | { 292 | if (ifreq->ifr_flags == AF_INET) 293 | { 294 | if (strcmp(ifreq->ifr_name, "lo") != 0) 295 | { 296 | return inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr); 297 | } 298 | ifreq++; 299 | } 300 | } 301 | return "0.0.0.0"; 302 | } -------------------------------------------------------------------------------- /src/rtsp/SocketOptions.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _SOCKETOPTION_H_ 26 | #define _SOCKETOPTION_H_ 27 | #include 28 | #include 29 | #include 30 | 31 | namespace SocketOptions 32 | { 33 | int createTcpSocket(); 34 | int createUdpSocket(); 35 | bool bind(int sockfd, std::string ip, uint16_t port); 36 | bool listen(int sockfd, int backlog); 37 | int accept(int sockfd); 38 | int readv(int sockfd, const struct iovec *iov, int iovcnt); 39 | int write(int sockfd, const void* buf, int size); 40 | int sendto(int sockfd, const void* buf, int len, const struct sockaddr *destAddr); 41 | void setNonBlock(int sockfd); 42 | void setBlock(int sockfd, int writeTimeout); 43 | void setReuseAddr(int sockfd, int on); 44 | void setReusePort(int sockfd); 45 | void setNonBlockAndCloseOnExec(int sockfd); 46 | void ignoreSigPipeOnSocket(int socketfd); 47 | void setNoDelay(int sockfd); 48 | void setKeepAlive(int sockfd); 49 | void setNoSigpipe(int sockfd); 50 | void setSendBufSize(int sockfd, int size); 51 | void setRecvBufSize(int sockfd, int size); 52 | std::string getPeerIp(int sockfd); 53 | int16_t getPeerPort(int sockfd); 54 | int getPeerAddr(int sockfd, struct sockaddr_in *addr); 55 | void close(int sockfd); 56 | bool connect(int sockfd, std::string ip, uint16_t port, int timeout); 57 | std::string getLocalIp(); 58 | } 59 | 60 | #endif -------------------------------------------------------------------------------- /src/rtsp/TcpConnect.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include "TcpConnect.h" 26 | #include "SocketOptions.h" 27 | #include "Mylog.h" 28 | #include 29 | #include 30 | 31 | TcpConnect::TcpConnect(int sockfd) : 32 | mSocket(sockfd), 33 | mDisconnectionCallback(NULL), 34 | mArg(NULL) 35 | { 36 | LOGI("Start constructor TcpConnect\n"); 37 | mTcpConnIOEvent = IOEvent::createNew(sockfd, this); 38 | mTcpConnIOEvent->setReadCallback(readCallback); 39 | mTcpConnIOEvent->setWriteCallback(writeCallback); 40 | mTcpConnIOEvent->setErrorCallback(errorCallback); 41 | mTcpConnIOEvent->enableReadHandling(); //默认只开启读 42 | mTcpConnIOEvent->setREvent(1); //默认只开启读 43 | //创建线程 44 | mTcpConnIOEvent->start(); 45 | LOGI("Start mTcpConnIOEvent successful\n"); 46 | } 47 | 48 | TcpConnect::~TcpConnect() 49 | { 50 | 51 | } 52 | 53 | void TcpConnect::setDisconnectionCallback(DisconnectionCallback callback, void* arg) 54 | { 55 | mDisconnectionCallback = callback; 56 | mArg = arg; 57 | } 58 | 59 | void TcpConnect::enableReadHandling() 60 | { 61 | if(mTcpConnIOEvent->isReadHandling()){ 62 | return; 63 | } 64 | mTcpConnIOEvent->enableReadHandling(); 65 | } 66 | 67 | void TcpConnect::enableWriteHandling() 68 | { 69 | if(mTcpConnIOEvent->isWriteHandling()) 70 | return; 71 | 72 | mTcpConnIOEvent->enableWriteHandling(); 73 | } 74 | 75 | void TcpConnect::enableErrorHandling() 76 | { 77 | if(mTcpConnIOEvent->isErrorHandling()) 78 | return; 79 | 80 | mTcpConnIOEvent->enableErrorHandling(); 81 | } 82 | 83 | void TcpConnect::disableReadeHandling() 84 | { 85 | if(!mTcpConnIOEvent->isReadHandling()) 86 | return; 87 | 88 | mTcpConnIOEvent->disableReadeHandling(); 89 | } 90 | 91 | void TcpConnect::disableWriteHandling() 92 | { 93 | if(!mTcpConnIOEvent->isWriteHandling()) 94 | return; 95 | 96 | mTcpConnIOEvent->disableWriteHandling(); 97 | } 98 | 99 | void TcpConnect::disableErrorHandling() 100 | { 101 | if(!mTcpConnIOEvent->isErrorHandling()) 102 | return; 103 | 104 | mTcpConnIOEvent->disableErrorHandling(); 105 | } 106 | 107 | void TcpConnect::handleRead() 108 | { 109 | int ret = mInputBuffer.read(mSocket.getSocketFd()); 110 | 111 | if(ret == 0) 112 | { 113 | LOGI("client disconnect\n"); 114 | handleDisconnection(); 115 | return; 116 | }else if(ret < 0) 117 | { 118 | LOGI("read err\n"); 119 | handleDisconnection(); 120 | return; 121 | } 122 | handleReadBytes(); 123 | } 124 | 125 | void TcpConnect::handleReadBytes() 126 | { 127 | LOGI("default read handle\n"); 128 | mInputBuffer.retrieveAll(); 129 | } 130 | 131 | void TcpConnect::handleWrite() 132 | { 133 | LOGI("default wirte handle\n"); 134 | mOutBuffer.retrieveAll(); 135 | } 136 | 137 | void TcpConnect::handleError() 138 | { 139 | LOGI("default error handle\n"); 140 | } 141 | 142 | void TcpConnect::readCallback(void* arg) 143 | { 144 | TcpConnect* Connect = (TcpConnect*)arg; 145 | Connect->handleRead(); 146 | } 147 | 148 | void TcpConnect::writeCallback(void* arg) 149 | { 150 | TcpConnect* Connect = (TcpConnect*)arg; 151 | Connect->handleWrite(); 152 | } 153 | 154 | void TcpConnect::errorCallback(void* arg) 155 | { 156 | TcpConnect* Connect = (TcpConnect*)arg; 157 | Connect->handleError(); 158 | } 159 | 160 | void TcpConnect::handleDisconnection() 161 | { 162 | if(mDisconnectionCallback) 163 | mDisconnectionCallback(mArg, mSocket.getSocketFd()); 164 | } -------------------------------------------------------------------------------- /src/rtsp/TcpConnect.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _TCP_CONNECT_H__ 26 | #define _TCP_CONNECT_H__ 27 | #include "TcpSocket.h" 28 | #include "DataBuffer.h" 29 | #include "Event.h" 30 | 31 | class TcpConnect 32 | { 33 | public: 34 | typedef void (*DisconnectionCallback)(void*, int); 35 | 36 | TcpConnect(int sockfd); 37 | virtual ~TcpConnect(); 38 | 39 | void setDisconnectionCallback(DisconnectionCallback callback, void* arg); 40 | 41 | protected: 42 | void enableReadHandling(); 43 | void enableWriteHandling(); 44 | void enableErrorHandling(); 45 | void disableReadeHandling(); 46 | void disableWriteHandling(); 47 | void disableErrorHandling(); 48 | 49 | void handleRead(); 50 | virtual void handleReadBytes(); 51 | virtual void handleWrite(); 52 | virtual void handleError(); 53 | 54 | void handleDisconnection(); 55 | 56 | private: 57 | static void readCallback(void* arg); 58 | static void writeCallback(void* arg); 59 | static void errorCallback(void* arg); 60 | 61 | protected: 62 | TcpSocket mSocket; 63 | IOEvent* mTcpConnIOEvent; 64 | DisconnectionCallback mDisconnectionCallback; 65 | void* mArg; 66 | DataBuffer mInputBuffer; 67 | DataBuffer mOutBuffer; 68 | char mBuffer[2048]; 69 | }; 70 | 71 | #endif -------------------------------------------------------------------------------- /src/rtsp/TcpServer.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include 27 | #include "TcpServer.h" 28 | #include 29 | #include "Mylog.h" 30 | 31 | 32 | TcpServer::TcpServer(Env* env,const Ipv4Address& addr) : 33 | mAddr(addr), 34 | mEnv(env) 35 | { 36 | mReceiver = Receiver::createNew(addr); 37 | assert(mReceiver); 38 | mReceiver->setNewConnectionCallback(newConnectionCallback, this); 39 | } 40 | TcpServer::~TcpServer() 41 | { 42 | delete mReceiver; 43 | mReceiver = nullptr; 44 | } 45 | 46 | void TcpServer::start() 47 | { 48 | mReceiver->listen(); 49 | mReceiver->doClient(); 50 | mEnv->start(); 51 | LOGI("TCP server start successfull\n"); 52 | 53 | } 54 | 55 | void TcpServer::newConnectionCallback(void * arg,ClientInfo* info) 56 | { 57 | TcpServer* tcpServer = (TcpServer*)arg; 58 | tcpServer->handleNewConnection(info); 59 | } 60 | -------------------------------------------------------------------------------- /src/rtsp/TcpServer.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _TCP_SERVER_H_ 26 | #define _TCP_SERVER_H_ 27 | #include 28 | #include "Receiver.h" 29 | #include "Ipv4Address.h" 30 | #include "Env.h" 31 | class TcpServer 32 | { 33 | public: 34 | virtual ~TcpServer(); 35 | 36 | void start(); 37 | protected: 38 | TcpServer(Env* env,const Ipv4Address& addr); 39 | virtual void handleNewConnection(ClientInfo* clientinfo) = 0; 40 | private: 41 | static void newConnectionCallback(void * arg,ClientInfo* ClientInfo); 42 | 43 | protected: 44 | Env* mEnv; 45 | Receiver* mReceiver; 46 | Ipv4Address mAddr; 47 | }; 48 | 49 | #endif -------------------------------------------------------------------------------- /src/rtsp/TcpSocket.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | 27 | #include "TcpSocket.h" 28 | #include "SocketOptions.h" 29 | 30 | TcpSocket::~TcpSocket() 31 | { 32 | SocketOptions::close(mSockfd); 33 | } 34 | 35 | bool TcpSocket::bind(Ipv4Address& addr) 36 | { 37 | return SocketOptions::bind(mSockfd, addr.getIp(), addr.getPort()); 38 | } 39 | 40 | bool TcpSocket::listen(int backlog) 41 | { 42 | return SocketOptions::listen(mSockfd, backlog); 43 | } 44 | 45 | int TcpSocket::accept() 46 | { 47 | return SocketOptions::accept(mSockfd); 48 | } 49 | 50 | void TcpSocket::setReuseAddr(int on) 51 | { 52 | SocketOptions::setReuseAddr(mSockfd, on); 53 | } -------------------------------------------------------------------------------- /src/rtsp/TcpSocket.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #ifndef _TCPSOCKET_H_ 26 | #define _TCPSOCKET_H_ 27 | #include 28 | #include 29 | 30 | #include "Ipv4Address.h" 31 | 32 | class TcpSocket 33 | { 34 | public: 35 | explicit TcpSocket(int sockfd) : 36 | mSockfd(sockfd) { } 37 | 38 | ~TcpSocket(); 39 | 40 | int getSocketFd() const { return mSockfd; } 41 | bool bind(Ipv4Address& addr); 42 | bool listen(int backlog); 43 | int accept(); 44 | void setReuseAddr(int on); 45 | 46 | private: 47 | int mSockfd; 48 | }; 49 | #endif -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(test) 2 | include_directories( 3 | ${RTSP_SRC_PATHH} 4 | ${ROOT_INCLUDE} 5 | ${Base_SRC_PATH} 6 | ) 7 | LINK_DIRECTORIES( 8 | ${LIB_PATH} 9 | ) 10 | link_libraries( 11 | rtspserver 12 | Env 13 | ) 14 | set(SRC1 ${TEST_PATH}/rtspserver_test.cpp) 15 | add_executable(rtspserverTest ${SRC1}) 16 | 17 | set(SRC2 ${TEST_PATH}/testTimeer.cpp) 18 | add_executable(testTimeer ${SRC2}) 19 | 20 | set(SRC3 ${TEST_PATH}/testSignalThread.cpp) 21 | add_executable(testSignalThread ${SRC3}) 22 | -------------------------------------------------------------------------------- /test/rtspserver_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include 27 | #include 28 | #include "RtspServer.h" 29 | #include "H264FileMediaSource.h" 30 | #include "H264RtpSink.h" 31 | #include "Env.h" 32 | using namespace std; 33 | 34 | int main(){ 35 | 36 | Ipv4Address addr(8554); 37 | Env* env = new Env(); 38 | RtspServer* rtspserver = RtspServer::createNew(env,addr); 39 | MediaSession* session = MediaSession::createNew("lsl"); 40 | MediaSource* videoSource = H264FileMediaSource::createNew(env,"enc.h264"); 41 | 42 | RtpSink* rtph264Sink = H264RtpSink::createNew(env,videoSource); 43 | session->addRtpSink(MediaSession::TrackId0, rtph264Sink); 44 | rtspserver->addMeidaSession(session); 45 | rtspserver->start(); 46 | 47 | while (1) 48 | { 49 | sleep(2); 50 | } 51 | 52 | 53 | return 0; 54 | } -------------------------------------------------------------------------------- /test/testSignalThread.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include "SignalEvent.h" 27 | #include "Mylog.h" 28 | 29 | using namespace std; 30 | void test(void* temp){ 31 | LOGI("test SignalEvent\n"); 32 | 33 | } 34 | int main(){ 35 | SignalEvent tt; 36 | tt.setCallBack(test,NULL); 37 | tt.start(); 38 | while(1){ 39 | LOGI("test1\n"); 40 | std::this_thread::sleep_for(std::chrono::microseconds(1*1000*1000)); 41 | LOGI("Set Now"); 42 | tt.setSignal(); 43 | } 44 | } -------------------------------------------------------------------------------- /test/testTimeer.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Copyright (c) 2020 Taoist Luo 3 | 4 | Create by: Taoist Luo 5 | CSDN:https://blog.csdn.net/daichanzhang9734/article/details/107549026 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | *****************************************************************************/ 25 | #include 26 | #include 27 | #include "TimeEventManager.h" 28 | #include "Mylog.h" 29 | #include "Env.h" 30 | // #define USE2 31 | // #define USE1 32 | #define USE3 33 | 34 | #ifdef USE1 //to 35 | TimeEventManager g_stTimer1; 36 | static int iCnt =0; 37 | void TimerEvent1(void* aa) 38 | { 39 | 40 | LOGI("TimerEvent1 %d execute...\n",iCnt++); 41 | if(iCnt >= 10) 42 | { 43 | g_stTimer1.stop(); 44 | } 45 | } 46 | #endif 47 | 48 | #ifdef USE2 49 | void TimerEvent2(void* id) 50 | { 51 | 52 | LOGI("TimerEvent2 execute...\n"); 53 | } 54 | 55 | void TimerEvent3(void* id) 56 | { 57 | 58 | LOGI("TimerEvent3 execute...\n"); 59 | } 60 | #endif 61 | 62 | 63 | #ifdef USE3 64 | void TimerEventVideo(void*pVideoId) 65 | { 66 | long iVideoId = (long)pVideoId; 67 | LOGI("TimerEventVideo execute id:%ld...\n",iVideoId); 68 | } 69 | 70 | void TimerEventAudio(void*pAudioId) 71 | { 72 | long iAudioId = (long)pAudioId; 73 | LOGI("TimerEventAudio execute id:%ld...\n",iAudioId); 74 | } 75 | void TimerEventtest(void*pAudioId) 76 | { 77 | long iAudioId = (long)pAudioId; 78 | LOGI("test..\n"); 79 | } 80 | 81 | #endif 82 | 83 | 84 | int main() 85 | { 86 | #ifdef USE1 87 | //Test loop execution task 88 | g_stTimer1.setEventCallback(TimerEvent1); 89 | //单位:us 90 | int64_t interval_time = 2000000; 91 | g_stTimer1.start(interval_time, true); 92 | LOGI("End of Usage 1 \n"); 93 | return 1; 94 | /////////Usage 1 END 95 | #endif 96 | 97 | #ifdef USE2 98 | long iVedioId = 0; 99 | TimerEventQueue stTimerQueue; 100 | stTimerQueue.addTimer(TimerEvent2, 6000, false,(void*)iVedioId); 101 | stTimerQueue.addTimer(TimerEvent3, 1000, false,(void*)iVedioId); 102 | 103 | int64_t iTimeRemain = stTimerQueue.getTimeRemaining(); 104 | while(iTimeRemain>0) 105 | { 106 | static int i = 0; 107 | usleep(iTimeRemain*1000); 108 | stTimerQueue.handleTimerEvent(); 109 | iTimeRemain = stTimerQueue.getTimeRemaining(); 110 | } 111 | 112 | //Usage 2 END 113 | 114 | return 1; 115 | #endif 116 | 117 | #ifdef USE3 118 | TimerEventQueue stTimerQueue; 119 | LOGI("Send First Video Frame...\n"); 120 | long iVedioId = 0; 121 | LOGI("Send First Audio Frame...\n"); 122 | long iAudioId = 1; 123 | Env env; 124 | env.addTimer(TimerEventVideo, 40, true,(void*)iVedioId); 125 | env.addTimer(TimerEventAudio, 23, true,(void*)iAudioId); 126 | env.start(); 127 | TimeEventManager::mSleep(2000); 128 | LOGI("test add when running"); 129 | env.addTimer(TimerEventtest, 40, false,(void*)iAudioId); 130 | while (1){ 131 | LOGI("in main"); 132 | TimeEventManager::mSleep(500); 133 | } 134 | return 1; 135 | 136 | #endif 137 | 138 | } 139 | --------------------------------------------------------------------------------