From 2cd03084070b646330ffd85949e2d66ea11e06ac Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Tue, 4 May 2021 20:31:16 +0200 Subject: [PATCH 01/21] fix for Apple --- src/net/EventLoop.cpp | 30 +++++++++++++++--------------- src/net/Socket.h | 19 +++++++++++-------- src/net/SocketUtil.cpp | 31 +++++++++++++++---------------- src/xop/rtsp.h | 8 +++----- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/net/EventLoop.cpp b/src/net/EventLoop.cpp index 5f99c53..aebca39 100644 --- a/src/net/EventLoop.cpp +++ b/src/net/EventLoop.cpp @@ -3,14 +3,14 @@ #include "EventLoop.h" -#if defined(WIN32) || defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) #include #endif -#if defined(WIN32) || defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) #pragma comment(lib, "Ws2_32.lib") #pragma comment(lib,"Iphlpapi.lib") -#endif +#endif using namespace xop; @@ -41,7 +41,7 @@ std::shared_ptr EventLoop::GetTaskScheduler() index_++; if (index_ >= task_schedulers_.size()) { index_ = 1; - } + } return task_scheduler; } @@ -56,9 +56,9 @@ void EventLoop::Loop() return ; } - for (uint32_t n = 0; n < num_threads_; n++) + for (uint32_t n = 0; n < num_threads_; n++) { -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(__APPLE__) std::shared_ptr task_scheduler_ptr(new EpollTaskScheduler(n)); #elif defined(WIN32) || defined(_WIN32) || defined(__FreeBSD__) std::shared_ptr task_scheduler_ptr(new SelectTaskScheduler(n)); @@ -71,12 +71,12 @@ void EventLoop::Loop() const int priority = TASK_SCHEDULER_PRIORITY_REALTIME; - for (auto iter : threads_) + for (auto iter : threads_) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) -#elif defined(WIN32) || defined(_WIN32) - switch (priority) +#elif defined(WIN32) || defined(_WIN32) + switch (priority) { case TASK_SCHEDULER_PRIORITY_LOW: SetThreadPriority(iter->native_handle(), THREAD_PRIORITY_BELOW_NORMAL); @@ -113,13 +113,13 @@ void EventLoop::Quit() task_schedulers_.clear(); threads_.clear(); } - + void EventLoop::UpdateChannel(ChannelPtr channel) { std::lock_guard locker(mutex_); if (task_schedulers_.size() > 0) { task_schedulers_[0]->UpdateChannel(channel); - } + } } void EventLoop::RemoveChannel(ChannelPtr& channel) @@ -127,7 +127,7 @@ void EventLoop::RemoveChannel(ChannelPtr& channel) std::lock_guard locker(mutex_); if (task_schedulers_.size() > 0) { task_schedulers_[0]->RemoveChannel(channel); - } + } } TimerId EventLoop::AddTimer(TimerEvent timerEvent, uint32_t msec) @@ -144,11 +144,11 @@ void EventLoop::RemoveTimer(TimerId timerId) std::lock_guard locker(mutex_); if (task_schedulers_.size() > 0) { task_schedulers_[0]->RemoveTimer(timerId); - } + } } bool EventLoop::AddTriggerEvent(TriggerEvent callback) -{ +{ std::lock_guard locker(mutex_); if (task_schedulers_.size() > 0) { return task_schedulers_[0]->AddTriggerEvent(callback); diff --git a/src/net/Socket.h b/src/net/Socket.h index d923cdd..d5f73bb 100644 --- a/src/net/Socket.h +++ b/src/net/Socket.h @@ -4,15 +4,18 @@ #ifndef XOP_SOCKET_H #define XOP_SOCKET_H -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) -#include +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#include #include #include -#include +#include +#if !defined(__APPLE__) + #include + #include + #include +#endif #include #include -#include -#include #include #include #include @@ -21,9 +24,9 @@ #include #define SOCKET int #define INVALID_SOCKET (-1) -#define SOCKET_ERROR (-1) +#define SOCKET_ERROR (-1) -#elif defined(WIN32) || defined(_WIN32) +#elif defined(WIN32) || defined(_WIN32) #define FD_SETSIZE 1024 #define WIN32_LEAN_AND_MEAN #define _WINSOCK_DEPRECATED_NO_WARNINGS @@ -32,7 +35,7 @@ #include #include #define SHUT_RD 0 -#define SHUT_WR 1 +#define SHUT_WR 1 #define SHUT_RDWR 2 #else diff --git a/src/net/SocketUtil.cpp b/src/net/SocketUtil.cpp index 6c99930..d3f476f 100644 --- a/src/net/SocketUtil.cpp +++ b/src/net/SocketUtil.cpp @@ -9,12 +9,12 @@ using namespace xop; bool SocketUtil::Bind(SOCKET sockfd, std::string ip, uint16_t port) { - struct sockaddr_in addr = {0}; - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr(ip.c_str()); - addr.sin_port = htons(port); + struct sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(ip.c_str()); + addr.sin_port = htons(port); - if(::bind(sockfd, (struct sockaddr*)&addr, sizeof addr) == SOCKET_ERROR) { + if(::bind(sockfd, (struct sockaddr*)&addr, sizeof addr) == SOCKET_ERROR) { return false; } @@ -23,7 +23,7 @@ bool SocketUtil::Bind(SOCKET sockfd, std::string ip, uint16_t port) void SocketUtil::SetNonBlock(SOCKET fd) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); #elif defined(WIN32) || defined(_WIN32) @@ -34,7 +34,7 @@ void SocketUtil::SetNonBlock(SOCKET fd) void SocketUtil::SetBlock(SOCKET fd, int write_timeout) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags&(~O_NONBLOCK)); #elif defined(WIN32) || defined(_WIN32) @@ -45,14 +45,14 @@ void SocketUtil::SetBlock(SOCKET fd, int write_timeout) if(write_timeout > 0) { #ifdef SO_SNDTIMEO -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) struct timeval tv = {write_timeout/1000, (write_timeout%1000)*1000}; setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof tv); #elif defined(WIN32) || defined(_WIN32) unsigned long ms = (unsigned long)write_timeout; setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&ms, sizeof(unsigned long)); #else -#endif +#endif #endif } } @@ -68,7 +68,7 @@ void SocketUtil::SetReusePort(SOCKET sockfd) #ifdef SO_REUSEPORT int on = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&on, sizeof(on)); -#endif +#endif } void SocketUtil::SetNoDelay(SOCKET sockfd) @@ -100,7 +100,7 @@ void SocketUtil::SetSendBufSize(SOCKET sockfd, int size) void SocketUtil::SetRecvBufSize(SOCKET sockfd, int size) { - if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size)) < 0) + if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size)) < 0) std::cerr << "Error setting SO_RCVBUF to " << size << std::endl; } @@ -168,7 +168,7 @@ int SocketUtil::GetPeerAddr(SOCKET sockfd, struct sockaddr_in *addr) void SocketUtil::Close(SOCKET sockfd) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) ::close(sockfd); #elif defined(WIN32) || defined(_WIN32) ::closesocket(sockfd); @@ -189,7 +189,7 @@ bool SocketUtil::Connect(SOCKET sockfd, std::string ip, uint16_t port, int timeo addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip.c_str()); - if (::connect(sockfd, (struct sockaddr*)&addr, addrlen) == SOCKET_ERROR) { + if (::connect(sockfd, (struct sockaddr*)&addr, addrlen) == SOCKET_ERROR) { if (timeout > 0) { is_connected = false; fd_set fd_write; @@ -204,9 +204,8 @@ bool SocketUtil::Connect(SOCKET sockfd, std::string ip, uint16_t port, int timeo } else { is_connected = false; - } + } } - + return is_connected; } - diff --git a/src/xop/rtsp.h b/src/xop/rtsp.h index 75b444e..ee738d8 100644 --- a/src/xop/rtsp.h +++ b/src/xop/rtsp.h @@ -30,7 +30,7 @@ class Rtsp : public std::enable_shared_from_this Rtsp() : has_auth_info_(false), authenticator_(nullptr) {} virtual ~Rtsp() {} - virtual void SetAuthenticator(std::shared_ptrauthenticator) + virtual void SetAuthenticator(std::shared_ptrauthenticator) { std::cerr << "Setting Authenticator" << std::endl; authenticator_ = authenticator; @@ -51,7 +51,7 @@ class Rtsp : public std::enable_shared_from_this char ip[100] = { 0 }; char suffix[100] = { 0 }; uint16_t port = 0; -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) if (sscanf(url.c_str() + 7, "%[^:]:%hu/%s", ip, &port, suffix) == 3) #elif defined(WIN32) || defined(_WIN32) if (sscanf_s(url.c_str() + 7, "%[^:]:%hu/%s", ip, 100, &port, suffix, 100) == 3) @@ -59,7 +59,7 @@ class Rtsp : public std::enable_shared_from_this { rtsp_url_info_.port = port; } -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) else if (sscanf(url.c_str() + 7, "%[^/]/%s", ip, suffix) == 2) #elif defined(WIN32) || defined(_WIN32) else if (sscanf_s(url.c_str() + 7, "%[^/]/%s", ip, 100, suffix, 100) == 2) @@ -97,5 +97,3 @@ class Rtsp : public std::enable_shared_from_this } #endif - - From 7274cac75358b6739ac38b0091a1034c972460ba Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Tue, 4 May 2021 21:25:04 +0200 Subject: [PATCH 02/21] major fix to run on Apple --- example/rtsp_h264_file.cpp | 57 ++++++++++++++++----------------- example/rtsp_pusher.cpp | 47 ++++++++++++++------------- src/net/BufferWriter.cpp | 2 +- src/net/EpollTaskScheduler.cpp | 13 +++++++- src/net/EventLoop.cpp | 4 +-- src/net/NetInterface.cpp | 2 +- src/net/Pipe.cpp | 20 ++++++++++-- src/net/SelectTaskScheduler.cpp | 2 +- src/net/SelectTaskScheduler.h | 2 +- src/net/TaskScheduler.cpp | 4 +-- src/net/TcpSocket.cpp | 2 +- src/net/Timestamp.cpp | 4 +-- src/xop/AACSource.cpp | 4 +-- src/xop/G711ASource.cpp | 4 +-- src/xop/H264Source.cpp | 4 +-- src/xop/H265Source.cpp | 6 ++-- 16 files changed, 101 insertions(+), 76 deletions(-) diff --git a/example/rtsp_h264_file.cpp b/example/rtsp_h264_file.cpp index 5b07ad4..53f8462 100644 --- a/example/rtsp_h264_file.cpp +++ b/example/rtsp_h264_file.cpp @@ -20,7 +20,7 @@ class H264File { return (m_file != NULL); } int ReadFrame(char* in_buf, int in_buf_size, bool* end); - + private: FILE *m_file = NULL; char *m_buf = NULL; @@ -32,7 +32,7 @@ class H264File void SendFrameThread(xop::RtspServer* rtsp_server, xop::MediaSessionId session_id, H264File* h264_file); int main(int argc, char **argv) -{ +{ if(argc != 2) { printf("Usage: %s test.h264 \n", argv[0]); return 0; @@ -48,7 +48,7 @@ int main(int argc, char **argv) std::string ip = "127.0.0.1"; std::string port = "554"; std::string rtsp_url = "rtsp://" + ip + ":" + port + "/" + suffix; - + std::shared_ptr event_loop(new xop::EventLoop()); std::shared_ptr server = xop::RtspServer::Create(event_loop.get()); @@ -61,21 +61,21 @@ int main(int argc, char **argv) server->SetAuthConfig("-_-", "admin", "12345"); #endif - xop::MediaSession *session = xop::MediaSession::CreateNew("live"); - session->AddSource(xop::channel_0, xop::H264Source::CreateNew()); - //session->StartMulticast(); + xop::MediaSession *session = xop::MediaSession::CreateNew("live"); + session->AddSource(xop::channel_0, xop::H264Source::CreateNew()); + //session->StartMulticast(); session->AddNotifyConnectedCallback([] (xop::MediaSessionId sessionId, std::string peer_ip, uint16_t peer_port){ printf("RTSP client connect, ip=%s, port=%hu \n", peer_ip.c_str(), peer_port); }); - + session->AddNotifyDisconnectedCallback([](xop::MediaSessionId sessionId, std::string peer_ip, uint16_t peer_port) { printf("RTSP client disconnect, ip=%s, port=%hu \n", peer_ip.c_str(), peer_port); }); xop::MediaSessionId session_id = server->AddSession(session); - + std::thread t1(SendFrameThread, server.get(), session_id, &h264_file); - t1.detach(); + t1.detach(); std::cout << "Play URL: " << rtsp_url << std::endl; @@ -88,7 +88,7 @@ int main(int argc, char **argv) } void SendFrameThread(xop::RtspServer* rtsp_server, xop::MediaSessionId session_id, H264File* h264_file) -{ +{ int buf_size = 2000000; std::unique_ptr frame_buf(new uint8_t[buf_size]); @@ -96,19 +96,20 @@ void SendFrameThread(xop::RtspServer* rtsp_server, xop::MediaSessionId session_i bool end_of_frame = false; int frame_size = h264_file->ReadFrame((char*)frame_buf.get(), buf_size, &end_of_frame); if(frame_size > 0) { - xop::AVFrame videoFrame = {0}; - videoFrame.type = 0; - videoFrame.size = frame_size; + xop::AVFrame videoFrame; + videoFrame.type = 0; videoFrame.timestamp = xop::H264Source::GetTimestamp(); - videoFrame.buffer.reset(new uint8_t[videoFrame.size]); - memcpy(videoFrame.buffer.get(), frame_buf.get(), videoFrame.size); + //videoFrame.buffer.reset(new uint8_t[videoFrame.size]); + //memcpy(videoFrame.buffer.get(), frame_buf.get(), videoFrame.size); + videoFrame.buffer.resize(frame_size); + memcpy(videoFrame.buffer.data(), frame_buf.get(), frame_size); rtsp_server->PushFrame(session_id, xop::channel_0, videoFrame); } else { break; } - - xop::Timer::Sleep(40); + + xop::Timer::Sleep(40); }; } @@ -126,7 +127,7 @@ H264File::~H264File() bool H264File::Open(const char *path) { m_file = fopen(path, "rb"); - if(m_file == NULL) { + if(m_file == NULL) { return false; } @@ -151,11 +152,11 @@ int H264File::ReadFrame(char* in_buf, int in_buf_size, bool* end) int bytes_read = (int)fread(m_buf, 1, m_buf_size, m_file); if(bytes_read == 0) { - fseek(m_file, 0, SEEK_SET); + fseek(m_file, 0, SEEK_SET); m_count = 0; m_bytes_used = 0; bytes_read = (int)fread(m_buf, 1, m_buf_size, m_file); - if(bytes_read == 0) { + if(bytes_read == 0) { this->Close(); return -1; } @@ -175,8 +176,8 @@ int H264File::ReadFrame(char* in_buf, int in_buf_size, bool* end) else { continue; } - - if (((m_buf[i+start_code]&0x1F) == 0x5 || (m_buf[i+start_code]&0x1F) == 0x1) + + if (((m_buf[i+start_code]&0x1F) == 0x5 || (m_buf[i+start_code]&0x1F) == 0x1) && ((m_buf[i+start_code+1]&0x80) == 0x80)) { is_find_start = true; i += 4; @@ -195,9 +196,9 @@ int H264File::ReadFrame(char* in_buf, int in_buf_size, bool* end) else { continue; } - - if (((m_buf[i+start_code]&0x1F) == 0x7) || ((m_buf[i+start_code]&0x1F) == 0x8) - || ((m_buf[i+start_code]&0x1F) == 0x6)|| (((m_buf[i+start_code]&0x1F) == 0x5 + + if (((m_buf[i+start_code]&0x1F) == 0x7) || ((m_buf[i+start_code]&0x1F) == 0x8) + || ((m_buf[i+start_code]&0x1F) == 0x6)|| (((m_buf[i+start_code]&0x1F) == 0x5 || (m_buf[i+start_code]&0x1F) == 0x1) &&((m_buf[i+start_code+1]&0x80) == 0x80))) { is_find_end = true; break; @@ -205,7 +206,7 @@ int H264File::ReadFrame(char* in_buf, int in_buf_size, bool* end) } bool flag = false; - if(is_find_start && !is_find_end && m_count>0) { + if(is_find_start && !is_find_end && m_count>0) { flag = is_find_end = true; i = bytes_read; *end = true; @@ -217,7 +218,7 @@ int H264File::ReadFrame(char* in_buf, int in_buf_size, bool* end) } int size = (i<=in_buf_size ? i : in_buf_size); - memcpy(in_buf, m_buf, size); + memcpy(in_buf, m_buf, size); if(!flag) { m_count += 1; @@ -231,5 +232,3 @@ int H264File::ReadFrame(char* in_buf, int in_buf_size, bool* end) fseek(m_file, m_bytes_used, SEEK_SET); return size; } - - diff --git a/example/rtsp_pusher.cpp b/example/rtsp_pusher.cpp index 1f15118..baf30bf 100755 --- a/example/rtsp_pusher.cpp +++ b/example/rtsp_pusher.cpp @@ -7,29 +7,29 @@ #include #include -#define PUSH_TEST "rtsp://10.11.165.203:554/test" +#define PUSH_TEST "rtsp://10.11.165.203:554/test" void snedFrameThread(xop::RtspPusher* rtspPusher); int main(int argc, char **argv) -{ - std::shared_ptr event_loop(new xop::EventLoop()); +{ + std::shared_ptr event_loop(new xop::EventLoop()); std::shared_ptr rtsp_pusher = xop::RtspPusher::Create(event_loop.get()); - xop::MediaSession *session = xop::MediaSession::CreateNew(); - session->AddSource(xop::channel_0, xop::H264Source::CreateNew()); + xop::MediaSession *session = xop::MediaSession::CreateNew(); + session->AddSource(xop::channel_0, xop::H264Source::CreateNew()); session->AddSource(xop::channel_1, xop::AACSource::CreateNew(44100, 2, false)); rtsp_pusher->AddSession(session); if (rtsp_pusher->OpenUrl(PUSH_TEST, 3000) < 0) { - std::cout << "Open " << PUSH_TEST << " failed." << std::endl; + std::cout << "Open " << PUSH_TEST << " failed." << std::endl; getchar(); return 0; } - std::cout << "Push stream to " << PUSH_TEST << " ..." << std::endl; - - std::thread thread(snedFrameThread, rtsp_pusher.get()); + std::cout << "Push stream to " << PUSH_TEST << " ..." << std::endl; + + std::thread thread(snedFrameThread, rtsp_pusher.get()); thread.detach(); while (1) { @@ -41,35 +41,36 @@ int main(int argc, char **argv) } void snedFrameThread(xop::RtspPusher* rtsp_pusher) -{ +{ while(rtsp_pusher->IsConnected()) - { - { - /* + { + { +/* //获取一帧 H264, 打包 - xop::AVFrame videoFrame = {0}; - //videoFrame.size = video frame size; // 视频帧大小 + xop::AVFrame videoFrame; + //videoFrame.size = video frame size; // 视频帧大小 videoFrame.timestamp = xop::H264Source::GetTimestamp(); // 时间戳, 建议使用编码器提供的时间戳 - videoFrame.buffer.reset(new uint8_t[videoFrame.size]); - //memcpy(videoFrame.buffer.get(), video frame data, videoFrame.size); + videoFrame.buffer.resize(frame_size); + videoFrame.type = 0; + // memcpy(videoFrame.buffer.data(), frame_buf.get(), frame_size); rtsp_pusher->PushFrame(xop::channel_0, videoFrame); //推流到服务器, 接口线程安全 - */ +*/ } - - { + + { /* //获取一帧 AAC, 打包 xop::AVFrame audioFrame = {0}; - //audioFrame.size = audio frame size; // 音频帧大小 + //audioFrame.size = audio frame size; // 音频帧大小 audioFrame.timestamp = xop::AACSource::GetTimestamp(44100); // 时间戳 audioFrame.buffer.reset(new uint8_t[audioFrame.size]); //memcpy(audioFrame.buffer.get(), audio frame data, audioFrame.size); rtsp_pusher->PushFrame(xop::channel_1, audioFrame); //推流到服务器, 接口线程安全 */ - } + } - xop::Timer::Sleep(1); + xop::Timer::Sleep(1); } } diff --git a/src/net/BufferWriter.cpp b/src/net/BufferWriter.cpp index 941d337..20ce7b3 100644 --- a/src/net/BufferWriter.cpp +++ b/src/net/BufferWriter.cpp @@ -115,7 +115,7 @@ int BufferWriter::Send(SOCKET sockfd, int timeout) } } else if (ret < 0) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) if (errno == EINTR || errno == EAGAIN) #elif defined(WIN32) || defined(_WIN32) int error = WSAGetLastError(); diff --git a/src/net/EpollTaskScheduler.cpp b/src/net/EpollTaskScheduler.cpp index 5dfa3a0..4089e4c 100644 --- a/src/net/EpollTaskScheduler.cpp +++ b/src/net/EpollTaskScheduler.cpp @@ -6,6 +6,7 @@ #if defined(__linux) || defined(__linux__) #include #include +#elif defined(__APPLE__) #endif using namespace xop; @@ -15,6 +16,8 @@ EpollTaskScheduler::EpollTaskScheduler(int id) { #if defined(__linux) || defined(__linux__) epollfd_ = epoll_create(1024); +#elif defined(__APPLE__) + #endif this->UpdateChannel(wakeup_channel_); } @@ -43,7 +46,9 @@ void EpollTaskScheduler::UpdateChannel(ChannelPtr channel) channels_.emplace(fd, channel); Update(EPOLL_CTL_ADD, channel); } - } + } +#elif defined(__APPLE__) + #endif } @@ -60,6 +65,8 @@ void EpollTaskScheduler::Update(int operation, ChannelPtr& channel) if(::epoll_ctl(epollfd_, operation, channel->GetSocket(), &event) < 0) { } +#elif defined(__APPLE__) + #endif } @@ -73,6 +80,8 @@ void EpollTaskScheduler::RemoveChannel(ChannelPtr& channel) Update(EPOLL_CTL_DEL, channel); channels_.erase(fd); } +#elif defined(__APPLE__) + #endif } @@ -95,6 +104,8 @@ bool EpollTaskScheduler::HandleEvent(int timeout) } } return true; +#elif defined(__APPLE__) + return false; #else return false; #endif diff --git a/src/net/EventLoop.cpp b/src/net/EventLoop.cpp index aebca39..3ce0794 100644 --- a/src/net/EventLoop.cpp +++ b/src/net/EventLoop.cpp @@ -58,9 +58,9 @@ void EventLoop::Loop() for (uint32_t n = 0; n < num_threads_; n++) { -#if defined(__linux) || defined(__linux__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) std::shared_ptr task_scheduler_ptr(new EpollTaskScheduler(n)); -#elif defined(WIN32) || defined(_WIN32) || defined(__FreeBSD__) +#elif defined(WIN32) || defined(_WIN32) || defined(__FreeBSD__) || defined(__APPLE__) std::shared_ptr task_scheduler_ptr(new SelectTaskScheduler(n)); #endif task_schedulers_.push_back(task_scheduler_ptr); diff --git a/src/net/NetInterface.cpp b/src/net/NetInterface.cpp index d4a0bda..c40924d 100644 --- a/src/net/NetInterface.cpp +++ b/src/net/NetInterface.cpp @@ -8,7 +8,7 @@ using namespace xop; std::string NetInterface::GetLocalIPAddress() { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) SOCKET sockfd = 0; char buf[512] = { 0 }; struct ifconf ifconf; diff --git a/src/net/Pipe.cpp b/src/net/Pipe.cpp index e34e850..739a014 100644 --- a/src/net/Pipe.cpp +++ b/src/net/Pipe.cpp @@ -7,6 +7,10 @@ #include #include +#if defined(__APPLE__) + #include +#endif + using namespace xop; Pipe::Pipe() @@ -55,6 +59,16 @@ bool Pipe::Create() if (pipe2(pipe_fd_, O_NONBLOCK | O_CLOEXEC) < 0) { return false; } +#elif defined(__APPLE__) + if(pipe(pipe_fd_) < 0) + return false; + if(fcntl(pipe_fd_[0],F_SETFL,O_NONBLOCK | O_CLOEXEC) < 0) + return false; + if(fcntl(pipe_fd_[1],F_SETFL,O_NONBLOCK | O_CLOEXEC) < 0) + return false; + //if (pipe2(pipe_fd_, O_NONBLOCK | O_CLOEXEC) < 0) { + // return false; + //} #endif return true; } @@ -63,7 +77,7 @@ int Pipe::Write(void *buf, int len) { #if defined(WIN32) || defined(_WIN32) return ::send(pipe_fd_[1], (char *)buf, len, 0); -#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) return ::write(pipe_fd_[1], buf, len); #endif } @@ -72,7 +86,7 @@ int Pipe::Read(void *buf, int len) { #if defined(WIN32) || defined(_WIN32) return recv(pipe_fd_[0], (char *)buf, len, 0); -#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) return ::read(pipe_fd_[0], buf, len); #endif } @@ -82,7 +96,7 @@ void Pipe::Close() #if defined(WIN32) || defined(_WIN32) closesocket(pipe_fd_[0]); closesocket(pipe_fd_[1]); -#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) ::close(pipe_fd_[0]); ::close(pipe_fd_[1]); #endif diff --git a/src/net/SelectTaskScheduler.cpp b/src/net/SelectTaskScheduler.cpp index acce1c9..6d01d86 100644 --- a/src/net/SelectTaskScheduler.cpp +++ b/src/net/SelectTaskScheduler.cpp @@ -158,7 +158,7 @@ bool SelectTaskScheduler::HandleEvent(int timeout) struct timeval tv = { timeout/1000, timeout%1000*1000 }; int ret = select((int)maxfd_+1, &fd_read, &fd_write, &fd_exp, &tv); if (ret < 0) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) if(errno == EINTR) { return true; } diff --git a/src/net/SelectTaskScheduler.h b/src/net/SelectTaskScheduler.h index 6e753e9..3cdc547 100644 --- a/src/net/SelectTaskScheduler.h +++ b/src/net/SelectTaskScheduler.h @@ -9,7 +9,7 @@ #include #include -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) #include #include #include diff --git a/src/net/TaskScheduler.cpp b/src/net/TaskScheduler.cpp index ab5d91d..10f6f9e 100644 --- a/src/net/TaskScheduler.cpp +++ b/src/net/TaskScheduler.cpp @@ -1,5 +1,5 @@ #include "TaskScheduler.h" -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) #include #endif @@ -36,7 +36,7 @@ TaskScheduler::~TaskScheduler() void TaskScheduler::Start() { #if 0 -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) signal(SIGPIPE, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGUSR1, SIG_IGN); diff --git a/src/net/TcpSocket.cpp b/src/net/TcpSocket.cpp index 5178678..49144ca 100644 --- a/src/net/TcpSocket.cpp +++ b/src/net/TcpSocket.cpp @@ -71,7 +71,7 @@ bool TcpSocket::Connect(std::string ip, uint16_t port, int timeout) void TcpSocket::Close() { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) ::close(sockfd_); #elif defined(WIN32) || defined(_WIN32) closesocket(sockfd_); diff --git a/src/net/Timestamp.cpp b/src/net/Timestamp.cpp index 7f1c981..29e575f 100644 --- a/src/net/Timestamp.cpp +++ b/src/net/Timestamp.cpp @@ -17,11 +17,11 @@ std::string Timestamp::Localtime() struct tm tm; localtime_s(&tm, &tt); stream << std::put_time(&tm, "%F %T"); -#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) char buffer[200] = {0}; std::string timeString; std::strftime(buffer, 200, "%F %T", std::localtime(&tt)); stream << buffer; #endif return stream.str(); -} \ No newline at end of file +} diff --git a/src/xop/AACSource.cpp b/src/xop/AACSource.cpp index 3dcdd30..ba6f685 100644 --- a/src/xop/AACSource.cpp +++ b/src/xop/AACSource.cpp @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-5-16 #if defined(WIN32) || defined(_WIN32) @@ -10,7 +10,7 @@ #include #include #include -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(__APPLE__) #include #endif diff --git a/src/xop/G711ASource.cpp b/src/xop/G711ASource.cpp index 2d3400b..29b550c 100644 --- a/src/xop/G711ASource.cpp +++ b/src/xop/G711ASource.cpp @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-5-16 #if defined(WIN32) || defined(_WIN32) @@ -9,7 +9,7 @@ #include "G711ASource.h" #include #include -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(__APPLE__) #include #endif diff --git a/src/xop/H264Source.cpp b/src/xop/H264Source.cpp index dd64e55..e62ad78 100644 --- a/src/xop/H264Source.cpp +++ b/src/xop/H264Source.cpp @@ -10,7 +10,7 @@ #include "H264Source.h" #include #include -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(__APPLE__) #include #endif @@ -125,7 +125,7 @@ bool H264Source::HandleFrame(MediaChannelId channel_id, AVFrame frame) int64_t H264Source::GetTimestamp() { -/* #if defined(__linux) || defined(__linux__) +/* #if defined(__linux) || defined(__linux__) || defined(__APPLE__) struct timeval tv = {0}; gettimeofday(&tv, NULL); uint32_t ts = ((tv.tv_sec*1000)+((tv.tv_usec+500)/1000))*90; // 90: _clockRate/1000; diff --git a/src/xop/H265Source.cpp b/src/xop/H265Source.cpp index 3089e88..7ddd353 100644 --- a/src/xop/H265Source.cpp +++ b/src/xop/H265Source.cpp @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-6-7 #if defined(WIN32) || defined(_WIN32) @@ -10,7 +10,7 @@ #include "H265Source.h" #include #include -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(__APPLE__) #include #endif @@ -132,7 +132,7 @@ bool H265Source::HandleFrame(MediaChannelId channelId, AVFrame frame) int64_t H265Source::GetTimestamp() { -/* #if defined(__linux) || defined(__linux__) +/* #if defined(__linux) || defined(__linux__) || defined(__APPLE__) struct timeval tv = {0}; gettimeofday(&tv, NULL); uint32_t ts = ((tv.tv_sec*1000)+((tv.tv_usec+500)/1000))*90; // 90: _clockRate/1000; From 7bee05018698cf6b65ef25f73da57d7f7683ff95 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Thu, 6 May 2021 08:01:29 +0200 Subject: [PATCH 03/21] first test towards Android --- src/net/BufferWriter.cpp | 30 +++++++++--------- src/net/EpollTaskScheduler.cpp | 32 +++++++++---------- src/net/EventLoop.cpp | 4 +-- src/net/NetInterface.cpp | 8 ++--- src/net/Pipe.cpp | 28 ++++++++--------- src/net/SelectTaskScheduler.cpp | 37 +++++++++++----------- src/net/SelectTaskScheduler.h | 6 ++-- src/net/Socket.h | 2 +- src/net/SocketUtil.cpp | 8 ++--- src/net/TaskScheduler.cpp | 20 ++++++------ src/net/TcpSocket.cpp | 18 +++++------ src/net/Timestamp.cpp | 8 ++--- src/xop/AACSource.cpp | 6 ++-- src/xop/G711ASource.cpp | 11 +++---- src/xop/H264Source.cpp | 15 +++++---- src/xop/H265Source.cpp | 54 ++++++++++++++++----------------- src/xop/rtsp.h | 4 +-- 17 files changed, 140 insertions(+), 151 deletions(-) diff --git a/src/net/BufferWriter.cpp b/src/net/BufferWriter.cpp index 20ce7b3..a2e278f 100644 --- a/src/net/BufferWriter.cpp +++ b/src/net/BufferWriter.cpp @@ -49,22 +49,22 @@ void xop::WriteUint16LE(char* p, uint16_t value) p[1] = value >> 8; } -BufferWriter::BufferWriter(int capacity) +BufferWriter::BufferWriter(int capacity) : max_queue_length_(capacity) { - -} + +} bool BufferWriter::Append(std::shared_ptr data, uint32_t size, uint32_t index) { if (size <= index) { return false; } - + if ((int)buffer_.size() >= max_queue_length_) { return false; } - + Packet pkt = { data, size, index }; buffer_.emplace(std::move(pkt)); return true; @@ -75,11 +75,11 @@ bool BufferWriter::Append(const char* data, uint32_t size, uint32_t index) if (size <= index) { return false; } - + if ((int)buffer_.size() >= max_queue_length_) { return false; } - + Packet pkt; pkt.data.reset(new char[size+512]); memcpy(pkt.data.get(), data, size); @@ -90,11 +90,11 @@ bool BufferWriter::Append(const char* data, uint32_t size, uint32_t index) } int BufferWriter::Send(SOCKET sockfd, int timeout) -{ +{ if (timeout > 0) { - SocketUtil::SetBlock(sockfd, timeout); + SocketUtil::SetBlock(sockfd, timeout); } - + int ret = 0; int count = 1; @@ -103,7 +103,7 @@ int BufferWriter::Send(SOCKET sockfd, int timeout) if (buffer_.empty()) { return 0; } - + count -= 1; Packet &pkt = buffer_.front(); ret = ::send(sockfd, pkt.data.get() + pkt.writeIndex, pkt.size - pkt.writeIndex, 0); @@ -115,8 +115,8 @@ int BufferWriter::Send(SOCKET sockfd, int timeout) } } else if (ret < 0) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) - if (errno == EINTR || errno == EAGAIN) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) + if (errno == EINTR || errno == EAGAIN) #elif defined(WIN32) || defined(_WIN32) int error = WSAGetLastError(); if (error == WSAEWOULDBLOCK || error == WSAEINPROGRESS || error == 0) @@ -130,8 +130,6 @@ int BufferWriter::Send(SOCKET sockfd, int timeout) if (timeout > 0) { SocketUtil::SetNonBlock(sockfd); } - + return ret; } - - diff --git a/src/net/EpollTaskScheduler.cpp b/src/net/EpollTaskScheduler.cpp index 4089e4c..d3682ae 100644 --- a/src/net/EpollTaskScheduler.cpp +++ b/src/net/EpollTaskScheduler.cpp @@ -3,7 +3,7 @@ #include "EpollTaskScheduler.h" -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(ANDROID) #include #include #elif defined(__APPLE__) @@ -14,23 +14,23 @@ using namespace xop; EpollTaskScheduler::EpollTaskScheduler(int id) : TaskScheduler(id) { -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(ANDROID) epollfd_ = epoll_create(1024); #elif defined(__APPLE__) - + #endif this->UpdateChannel(wakeup_channel_); } EpollTaskScheduler::~EpollTaskScheduler() { - + } void EpollTaskScheduler::UpdateChannel(ChannelPtr channel) { std::lock_guard lock(mutex_); -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(ANDROID) int fd = channel->GetSocket(); if(channels_.find(fd) != channels_.end()) { if(channel->IsNoneEvent()) { @@ -45,16 +45,16 @@ void EpollTaskScheduler::UpdateChannel(ChannelPtr channel) if(!channel->IsNoneEvent()) { channels_.emplace(fd, channel); Update(EPOLL_CTL_ADD, channel); - } + } } #elif defined(__APPLE__) - + #endif } void EpollTaskScheduler::Update(int operation, ChannelPtr& channel) { -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(ANDROID) struct epoll_event event = {0}; if(operation != EPOLL_CTL_DEL) { @@ -66,14 +66,14 @@ void EpollTaskScheduler::Update(int operation, ChannelPtr& channel) } #elif defined(__APPLE__) - + #endif } void EpollTaskScheduler::RemoveChannel(ChannelPtr& channel) { std::lock_guard lock(mutex_); -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(ANDROID) int fd = channel->GetSocket(); if(channels_.find(fd) != channels_.end()) { @@ -81,13 +81,13 @@ void EpollTaskScheduler::RemoveChannel(ChannelPtr& channel) channels_.erase(fd); } #elif defined(__APPLE__) - + #endif } bool EpollTaskScheduler::HandleEvent(int timeout) { -#if defined(__linux) || defined(__linux__) +#if defined(__linux) || defined(__linux__) || defined(ANDROID) struct epoll_event events[512] = {0}; int num_events = -1; @@ -95,14 +95,14 @@ bool EpollTaskScheduler::HandleEvent(int timeout) if(num_events < 0) { if(errno != EINTR) { return false; - } + } } for(int n=0; nHandleEvent(events[n].events); } - } + } return true; #elif defined(__APPLE__) return false; @@ -110,5 +110,3 @@ bool EpollTaskScheduler::HandleEvent(int timeout) return false; #endif } - - diff --git a/src/net/EventLoop.cpp b/src/net/EventLoop.cpp index 3ce0794..a0e42ff 100644 --- a/src/net/EventLoop.cpp +++ b/src/net/EventLoop.cpp @@ -60,7 +60,7 @@ void EventLoop::Loop() { #if defined(__linux) || defined(__linux__) std::shared_ptr task_scheduler_ptr(new EpollTaskScheduler(n)); -#elif defined(WIN32) || defined(_WIN32) || defined(__FreeBSD__) || defined(__APPLE__) +#elif defined(WIN32) || defined(_WIN32) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) std::shared_ptr task_scheduler_ptr(new SelectTaskScheduler(n)); #endif task_schedulers_.push_back(task_scheduler_ptr); @@ -73,7 +73,7 @@ void EventLoop::Loop() for (auto iter : threads_) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) #elif defined(WIN32) || defined(_WIN32) switch (priority) diff --git a/src/net/NetInterface.cpp b/src/net/NetInterface.cpp index c40924d..2bb1e3c 100644 --- a/src/net/NetInterface.cpp +++ b/src/net/NetInterface.cpp @@ -8,7 +8,7 @@ using namespace xop; std::string NetInterface::GetLocalIPAddress() { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) SOCKET sockfd = 0; char buf[512] = { 0 }; struct ifconf ifconf; @@ -69,12 +69,12 @@ std::string NetInterface::GetLocalIPAddress() if (strcmp(pIpAddrString->IpAddress.String, "127.0.0.1")!=0 && strcmp(pIpAddrString->IpAddress.String, "0.0.0.0")!=0) { - // pIpAddrString->IpMask.String + // pIpAddrString->IpMask.String //pIpAdapterInfo->GatewayList.IpAddress.String std::string ip(pIpAddrString->IpAddress.String); //delete pIpAdapterInfo; return ip; - } + } pIpAddrString = pIpAddrString->Next; } while (pIpAddrString); pIpAdapterInfo = pIpAdapterInfo->Next; @@ -86,5 +86,3 @@ std::string NetInterface::GetLocalIPAddress() return "0.0.0.0"; #endif } - - diff --git a/src/net/Pipe.cpp b/src/net/Pipe.cpp index 739a014..26a5c62 100644 --- a/src/net/Pipe.cpp +++ b/src/net/Pipe.cpp @@ -20,7 +20,7 @@ Pipe::Pipe() bool Pipe::Create() { -#if defined(WIN32) || defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) TcpSocket rp(socket(AF_INET, SOCK_STREAM, 0)), wp(socket(AF_INET, SOCK_STREAM, 0)); std::random_device rd; @@ -30,20 +30,20 @@ bool Pipe::Create() int again = 5; while(again--) { - port = rd(); + port = rd(); if (rp.Bind("127.0.0.1", port)) { break; - } + } } if (again == 0) { return false; } - + if (!rp.Listen(1)) { return false; } - + if (!wp.Connect("127.0.0.1", port)) { return false; } @@ -55,7 +55,7 @@ bool Pipe::Create() SocketUtil::SetNonBlock(pipe_fd_[0]); SocketUtil::SetNonBlock(pipe_fd_[1]); -#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) +#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(ANDROID) if (pipe2(pipe_fd_, O_NONBLOCK | O_CLOEXEC) < 0) { return false; } @@ -75,28 +75,28 @@ bool Pipe::Create() int Pipe::Write(void *buf, int len) { -#if defined(WIN32) || defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) return ::send(pipe_fd_[1], (char *)buf, len, 0); -#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) return ::write(pipe_fd_[1], buf, len); -#endif +#endif } int Pipe::Read(void *buf, int len) { -#if defined(WIN32) || defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) return recv(pipe_fd_[0], (char *)buf, len, 0); -#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) return ::read(pipe_fd_[0], buf, len); -#endif +#endif } void Pipe::Close() { -#if defined(WIN32) || defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) closesocket(pipe_fd_[0]); closesocket(pipe_fd_[1]); -#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) ::close(pipe_fd_[0]); ::close(pipe_fd_[1]); #endif diff --git a/src/net/SelectTaskScheduler.cpp b/src/net/SelectTaskScheduler.cpp index 6d01d86..0ad3958 100644 --- a/src/net/SelectTaskScheduler.cpp +++ b/src/net/SelectTaskScheduler.cpp @@ -25,7 +25,7 @@ SelectTaskScheduler::SelectTaskScheduler(int id) SelectTaskScheduler::~SelectTaskScheduler() { - + } void SelectTaskScheduler::UpdateChannel(ChannelPtr channel) @@ -52,8 +52,8 @@ void SelectTaskScheduler::UpdateChannel(ChannelPtr channel) is_fd_read_reset_ = true; is_fd_write_reset_ = true; is_fd_exp_reset_ = true; - } - } + } + } } void SelectTaskScheduler::RemoveChannel(ChannelPtr& channel) @@ -71,12 +71,12 @@ void SelectTaskScheduler::RemoveChannel(ChannelPtr& channel) } bool SelectTaskScheduler::HandleEvent(int timeout) -{ +{ if(channels_.empty()) { if (timeout <= 0) { timeout = 10; } - + Timer::Sleep(timeout); return true; } @@ -95,7 +95,7 @@ bool SelectTaskScheduler::HandleEvent(int timeout) if (is_fd_exp_reset_) { maxfd_ = 0; } - + std::lock_guard lock(mutex_); for(auto iter : channels_) { int events = iter.second->GetEvents(); @@ -114,9 +114,9 @@ bool SelectTaskScheduler::HandleEvent(int timeout) if(fd > maxfd_) { maxfd_ = fd; } - } + } } - + fd_read_reset = is_fd_read_reset_; fd_write_reset = is_fd_write_reset_; fd_exp_reset = is_fd_exp_reset_; @@ -124,15 +124,15 @@ bool SelectTaskScheduler::HandleEvent(int timeout) is_fd_write_reset_ = false; is_fd_exp_reset_ = false; } - + if(fd_read_reset) { FD_ZERO(&fd_read_backup_); - memcpy(&fd_read_backup_, &fd_read, sizeof(fd_set)); + memcpy(&fd_read_backup_, &fd_read, sizeof(fd_set)); } else { memcpy(&fd_read, &fd_read_backup_, sizeof(fd_set)); } - + if(fd_write_reset) { FD_ZERO(&fd_write_backup_); @@ -141,7 +141,7 @@ bool SelectTaskScheduler::HandleEvent(int timeout) else { memcpy(&fd_write, &fd_write_backup_, sizeof(fd_set)); } - + if(fd_exp_reset) { FD_ZERO(&fd_exp_backup_); @@ -156,13 +156,13 @@ bool SelectTaskScheduler::HandleEvent(int timeout) } struct timeval tv = { timeout/1000, timeout%1000*1000 }; - int ret = select((int)maxfd_+1, &fd_read, &fd_write, &fd_exp, &tv); + int ret = select((int)maxfd_+1, &fd_read, &fd_write, &fd_exp, &tv); if (ret < 0) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) if(errno == EINTR) { return true; - } -#endif + } +#endif return false; } @@ -189,7 +189,7 @@ bool SelectTaskScheduler::HandleEvent(int timeout) event_list.emplace_front(iter.second, events); } } - } + } for(auto& iter: event_list) { iter.first->HandleEvent(iter.second); @@ -197,6 +197,3 @@ bool SelectTaskScheduler::HandleEvent(int timeout) return true; } - - - diff --git a/src/net/SelectTaskScheduler.h b/src/net/SelectTaskScheduler.h index 3cdc547..1610ae9 100644 --- a/src/net/SelectTaskScheduler.h +++ b/src/net/SelectTaskScheduler.h @@ -9,7 +9,7 @@ #include #include -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) #include #include #include @@ -17,7 +17,7 @@ #endif namespace xop -{ +{ class SelectTaskScheduler : public TaskScheduler { @@ -28,7 +28,7 @@ class SelectTaskScheduler : public TaskScheduler void UpdateChannel(ChannelPtr channel); void RemoveChannel(ChannelPtr& channel); bool HandleEvent(int timeout); - + private: fd_set fd_read_backup_; fd_set fd_write_backup_; diff --git a/src/net/Socket.h b/src/net/Socket.h index d5f73bb..a693e90 100644 --- a/src/net/Socket.h +++ b/src/net/Socket.h @@ -4,7 +4,7 @@ #ifndef XOP_SOCKET_H #define XOP_SOCKET_H -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) #include #include #include diff --git a/src/net/SocketUtil.cpp b/src/net/SocketUtil.cpp index d3f476f..6386459 100644 --- a/src/net/SocketUtil.cpp +++ b/src/net/SocketUtil.cpp @@ -23,7 +23,7 @@ bool SocketUtil::Bind(SOCKET sockfd, std::string ip, uint16_t port) void SocketUtil::SetNonBlock(SOCKET fd) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); #elif defined(WIN32) || defined(_WIN32) @@ -34,7 +34,7 @@ void SocketUtil::SetNonBlock(SOCKET fd) void SocketUtil::SetBlock(SOCKET fd, int write_timeout) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags&(~O_NONBLOCK)); #elif defined(WIN32) || defined(_WIN32) @@ -45,7 +45,7 @@ void SocketUtil::SetBlock(SOCKET fd, int write_timeout) if(write_timeout > 0) { #ifdef SO_SNDTIMEO -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) struct timeval tv = {write_timeout/1000, (write_timeout%1000)*1000}; setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof tv); #elif defined(WIN32) || defined(_WIN32) @@ -168,7 +168,7 @@ int SocketUtil::GetPeerAddr(SOCKET sockfd, struct sockaddr_in *addr) void SocketUtil::Close(SOCKET sockfd) { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) ::close(sockfd); #elif defined(WIN32) || defined(_WIN32) ::closesocket(sockfd); diff --git a/src/net/TaskScheduler.cpp b/src/net/TaskScheduler.cpp index 10f6f9e..10d2b3f 100644 --- a/src/net/TaskScheduler.cpp +++ b/src/net/TaskScheduler.cpp @@ -1,5 +1,5 @@ #include "TaskScheduler.h" -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) #include #endif @@ -7,13 +7,13 @@ using namespace xop; TaskScheduler::TaskScheduler(int id) : id_(id) - , is_shutdown_(false) + , is_shutdown_(false) , wakeup_pipe_(new Pipe()) , trigger_events_(new xop::RingBuffer(kMaxTriggetEvents)) { static std::once_flag flag; std::call_once(flag, [] { -#if defined(WIN32) || defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) WSADATA wsa_data; if (WSAStartup(MAKEWORD(2, 2), &wsa_data)) { WSACleanup(); @@ -24,26 +24,26 @@ TaskScheduler::TaskScheduler(int id) if (wakeup_pipe_->Create()) { wakeup_channel_.reset(new Channel(wakeup_pipe_->Read())); wakeup_channel_->EnableReading(); - wakeup_channel_->SetReadCallback([this]() { this->Wake(); }); - } + wakeup_channel_->SetReadCallback([this]() { this->Wake(); }); + } } TaskScheduler::~TaskScheduler() { - + } void TaskScheduler::Start() { #if 0 -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) signal(SIGPIPE, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGKILL, SIG_IGN); -#endif -#endif +#endif +#endif is_shutdown_ = false; while (!is_shutdown_) { this->HandleTriggerEvent(); @@ -92,7 +92,7 @@ void TaskScheduler::Wake() void TaskScheduler::HandleTriggerEvent() { - do + do { TriggerEvent callback; if (trigger_events_->Pop(callback)) { diff --git a/src/net/TcpSocket.cpp b/src/net/TcpSocket.cpp index 49144ca..aaf8c8d 100644 --- a/src/net/TcpSocket.cpp +++ b/src/net/TcpSocket.cpp @@ -11,12 +11,12 @@ using namespace xop; TcpSocket::TcpSocket(SOCKET sockfd) : sockfd_(sockfd) { - + } TcpSocket::~TcpSocket() { - + } SOCKET TcpSocket::Create() @@ -27,10 +27,10 @@ SOCKET TcpSocket::Create() bool TcpSocket::Bind(std::string ip, uint16_t port) { - struct sockaddr_in addr = {0}; - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr(ip.c_str()); - addr.sin_port = htons(port); + struct sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(ip.c_str()); + addr.sin_port = htons(port); if(::bind(sockfd_, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) { LOG_DEBUG(" bind <%s:%u> failed.\n", sockfd_, ip.c_str(), port); @@ -60,7 +60,7 @@ SOCKET TcpSocket::Accept() } bool TcpSocket::Connect(std::string ip, uint16_t port, int timeout) -{ +{ if(!SocketUtil::Connect(sockfd_, ip, port, timeout)) { LOG_DEBUG(" connect failed.\n", sockfd_); return false; @@ -71,12 +71,12 @@ bool TcpSocket::Connect(std::string ip, uint16_t port, int timeout) void TcpSocket::Close() { -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) ::close(sockfd_); #elif defined(WIN32) || defined(_WIN32) closesocket(sockfd_); #else - + #endif sockfd_ = 0; } diff --git a/src/net/Timestamp.cpp b/src/net/Timestamp.cpp index 29e575f..6c0e47b 100644 --- a/src/net/Timestamp.cpp +++ b/src/net/Timestamp.cpp @@ -1,6 +1,6 @@ #include "Timestamp.h" #include -#include +#include #include using namespace xop; @@ -12,16 +12,16 @@ std::string Timestamp::Localtime() std::ostringstream stream; auto now = system_clock::now(); time_t tt = system_clock::to_time_t(now); - + #if defined(WIN32) || defined(_WIN32) struct tm tm; localtime_s(&tm, &tt); stream << std::put_time(&tm, "%F %T"); -#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) char buffer[200] = {0}; std::string timeString; std::strftime(buffer, 200, "%F %T", std::localtime(&tt)); stream << buffer; -#endif +#endif return stream.str(); } diff --git a/src/xop/AACSource.cpp b/src/xop/AACSource.cpp index ba6f685..dc3f7ff 100644 --- a/src/xop/AACSource.cpp +++ b/src/xop/AACSource.cpp @@ -10,7 +10,7 @@ #include #include #include -#if defined(__linux) || defined(__linux__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__APPLE__) || defined(ANDROID) #include #endif @@ -61,13 +61,13 @@ string AACSource::GetAttribute() // RFC 3640 for (index = 0; index < 16; index++) { if (AACSampleRate[index] == samplerate_) { break; - } + } } if (index == 16) { return ""; // error } - + uint8_t profile = 1; char config[10] = {0}; diff --git a/src/xop/G711ASource.cpp b/src/xop/G711ASource.cpp index 29b550c..d570789 100644 --- a/src/xop/G711ASource.cpp +++ b/src/xop/G711ASource.cpp @@ -1,7 +1,7 @@ // PHZ // 2018-5-16 -#if defined(WIN32) || defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif @@ -9,9 +9,9 @@ #include "G711ASource.h" #include #include -#if defined(__linux) || defined(__linux__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__APPLE__) || defined(ANDROID) #include -#endif +#endif using namespace xop; using namespace std; @@ -30,7 +30,7 @@ G711ASource* G711ASource::CreateNew() G711ASource::~G711ASource() { - + } string G711ASource::GetMediaDescription(uint16_t port) @@ -39,7 +39,7 @@ string G711ASource::GetMediaDescription(uint16_t port) sprintf(buf, "m=audio %hu RTP/AVP 8", port); return string(buf); } - + string G711ASource::GetAttribute() { return string("a=rtpmap:8 PCMA/8000/1"); @@ -74,4 +74,3 @@ int64_t G711ASource::GetTimestamp() auto time_point = chrono::time_point_cast(chrono::steady_clock::now()); return (int64_t)((time_point.time_since_epoch().count()+500)/1000*8); } - diff --git a/src/xop/H264Source.cpp b/src/xop/H264Source.cpp index e62ad78..84775b0 100644 --- a/src/xop/H264Source.cpp +++ b/src/xop/H264Source.cpp @@ -10,7 +10,7 @@ #include "H264Source.h" #include #include -#if defined(__linux) || defined(__linux__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__APPLE__) || defined(ANDROID) #include #endif @@ -20,7 +20,7 @@ using namespace std; H264Source::H264Source(uint32_t framerate) : framerate_(framerate) { - payload_ = 96; + payload_ = 96; media_type_ = H264; clock_rate_ = 90000; } @@ -54,7 +54,7 @@ bool H264Source::HandleFrame(MediaChannelId channel_id, AVFrame frame) if (frame.timestamp == 0) { frame.timestamp = GetTimestamp(); - } + } if (frame_size <= MAX_RTP_PAYLOAD_SIZE) { RtpPacket rtp_pkt; @@ -62,12 +62,12 @@ bool H264Source::HandleFrame(MediaChannelId channel_id, AVFrame frame) rtp_pkt.timestamp = frame.timestamp; rtp_pkt.size = frame_size + 4 + RTP_HEADER_SIZE; rtp_pkt.last = 1; - memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE, frame_buf, frame_size); + memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE, frame_buf, frame_size); if (send_frame_callback_) { if (!send_frame_callback_(channel_id, rtp_pkt)) { return false; - } + } } } else { char FU_A[2] = {0}; @@ -115,7 +115,7 @@ bool H264Source::HandleFrame(MediaChannelId channel_id, AVFrame frame) if (send_frame_callback_) { if (!send_frame_callback_(channel_id, rtp_pkt)) { return false; - } + } } } } @@ -125,7 +125,7 @@ bool H264Source::HandleFrame(MediaChannelId channel_id, AVFrame frame) int64_t H264Source::GetTimestamp() { -/* #if defined(__linux) || defined(__linux__) || defined(__APPLE__) +/* #if defined(__linux) || defined(__linux__) || defined(__APPLE__) || defined(ANDROID) struct timeval tv = {0}; gettimeofday(&tv, NULL); uint32_t ts = ((tv.tv_sec*1000)+((tv.tv_usec+500)/1000))*90; // 90: _clockRate/1000; @@ -135,4 +135,3 @@ int64_t H264Source::GetTimestamp() return (int64_t)((time_point.time_since_epoch().count() + 500) / 1000 * 90 ); //#endif } - diff --git a/src/xop/H265Source.cpp b/src/xop/H265Source.cpp index 7ddd353..9da35c3 100644 --- a/src/xop/H265Source.cpp +++ b/src/xop/H265Source.cpp @@ -1,7 +1,7 @@ // PHZ // 2018-6-7 -#if defined(WIN32) || defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif @@ -10,7 +10,7 @@ #include "H265Source.h" #include #include -#if defined(__linux) || defined(__linux__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__APPLE__) || defined(ANDROID) #include #endif @@ -32,7 +32,7 @@ H265Source* H265Source::CreateNew(uint32_t framerate) H265Source::~H265Source() { - + } string H265Source::GetMediaDescription(uint16_t port) @@ -41,7 +41,7 @@ string H265Source::GetMediaDescription(uint16_t port) sprintf(buf, "m=video %hu RTP/AVP 96", port); return string(buf); } - + string H265Source::GetAttribute() { return string("a=rtpmap:96 H265/90000"); @@ -55,7 +55,7 @@ bool H265Source::HandleFrame(MediaChannelId channelId, AVFrame frame) if (frame.timestamp == 0) { frame.timestamp = GetTimestamp(); } - + if (frame_size <= MAX_RTP_PAYLOAD_SIZE) { RtpPacket rtp_pkt; rtp_pkt.type = frame.type; @@ -64,23 +64,23 @@ bool H265Source::HandleFrame(MediaChannelId channelId, AVFrame frame) rtp_pkt.last = 1; memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE, frame_buf, frame_size); - + if (send_frame_callback_) { if (!send_frame_callback_(channelId, rtp_pkt)) { return false; - } + } } - } - else { - char FU[3] = {0}; - char nalUnitType = (frame_buf[0] & 0x7E) >> 1; - FU[0] = (frame_buf[0] & 0x81) | (49<<1); - FU[1] = frame_buf[1]; - FU[2] = (0x80 | nalUnitType); - + } + else { + char FU[3] = {0}; + char nalUnitType = (frame_buf[0] & 0x7E) >> 1; + FU[0] = (frame_buf[0] & 0x81) | (49<<1); + FU[1] = frame_buf[1]; + FU[2] = (0x80 | nalUnitType); + frame_buf += 2; frame_size -= 2; - + while (frame_size + 3 > MAX_RTP_PAYLOAD_SIZE) { RtpPacket rtp_pkt; rtp_pkt.type = frame.type; @@ -92,19 +92,19 @@ bool H265Source::HandleFrame(MediaChannelId channelId, AVFrame frame) rtp_pkt.data.get()[RTP_HEADER_SIZE+5] = FU[1]; rtp_pkt.data.get()[RTP_HEADER_SIZE+6] = FU[2]; memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE+3, frame_buf, MAX_RTP_PAYLOAD_SIZE-3); - + if (send_frame_callback_) { if (!send_frame_callback_(channelId, rtp_pkt)) { return false; - } + } } - + frame_buf += (MAX_RTP_PAYLOAD_SIZE - 3); frame_size -= (MAX_RTP_PAYLOAD_SIZE - 3); - - FU[2] &= ~0x80; + + FU[2] &= ~0x80; } - + { RtpPacket rtp_pkt; rtp_pkt.type = frame.type; @@ -117,13 +117,13 @@ bool H265Source::HandleFrame(MediaChannelId channelId, AVFrame frame) rtp_pkt.data.get()[RTP_HEADER_SIZE+5] = FU[1]; rtp_pkt.data.get()[RTP_HEADER_SIZE+6] = FU[2]; memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE+3, frame_buf, frame_size); - + if (send_frame_callback_) { if (!send_frame_callback_(channelId, rtp_pkt)) { return false; - } + } } - } + } } return true; @@ -132,7 +132,7 @@ bool H265Source::HandleFrame(MediaChannelId channelId, AVFrame frame) int64_t H265Source::GetTimestamp() { -/* #if defined(__linux) || defined(__linux__) || defined(__APPLE__) +/* #if defined(__linux) || defined(__linux__) || defined(__APPLE__) || defined(ANDROID) struct timeval tv = {0}; gettimeofday(&tv, NULL); uint32_t ts = ((tv.tv_sec*1000)+((tv.tv_usec+500)/1000))*90; // 90: _clockRate/1000; @@ -142,5 +142,5 @@ int64_t H265Source::GetTimestamp() //auto time_point = chrono::time_point_cast(chrono::steady_clock::now()); auto time_point = chrono::time_point_cast(chrono::steady_clock::now()); return (int64_t)((time_point.time_since_epoch().count() + 500) / 1000 * 90); -//#endif +//#endif } diff --git a/src/xop/rtsp.h b/src/xop/rtsp.h index ee738d8..df9d7e4 100644 --- a/src/xop/rtsp.h +++ b/src/xop/rtsp.h @@ -51,7 +51,7 @@ class Rtsp : public std::enable_shared_from_this char ip[100] = { 0 }; char suffix[100] = { 0 }; uint16_t port = 0; -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) if (sscanf(url.c_str() + 7, "%[^:]:%hu/%s", ip, &port, suffix) == 3) #elif defined(WIN32) || defined(_WIN32) if (sscanf_s(url.c_str() + 7, "%[^:]:%hu/%s", ip, 100, &port, suffix, 100) == 3) @@ -59,7 +59,7 @@ class Rtsp : public std::enable_shared_from_this { rtsp_url_info_.port = port; } -#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) else if (sscanf(url.c_str() + 7, "%[^/]/%s", ip, suffix) == 2) #elif defined(WIN32) || defined(_WIN32) else if (sscanf_s(url.c_str() + 7, "%[^/]/%s", ip, 100, suffix, 100) == 2) From 78f324251d1d4d3976e487f7dcaf17c0250de3bb Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Thu, 6 May 2021 10:33:32 +0200 Subject: [PATCH 04/21] android logging --- src/net/EpollTaskScheduler.cpp | 2 +- src/net/Pipe.cpp | 4 ++-- src/net/Socket.h | 7 +++++++ src/net/SocketUtil.cpp | 12 ++++++++++++ src/net/TcpConnection.cpp | 16 ++++++++++++---- src/net/TcpServer.cpp | 9 ++++++--- src/xop/RtpConnection.cpp | 23 +++++++++++++---------- src/xop/RtspConnection.cpp | 18 +++++++++++++++--- src/xop/RtspServer.cpp | 10 ++++++---- src/xop/rtsp.h | 7 +++++++ 10 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/net/EpollTaskScheduler.cpp b/src/net/EpollTaskScheduler.cpp index d3682ae..6be1488 100644 --- a/src/net/EpollTaskScheduler.cpp +++ b/src/net/EpollTaskScheduler.cpp @@ -18,7 +18,7 @@ EpollTaskScheduler::EpollTaskScheduler(int id) epollfd_ = epoll_create(1024); #elif defined(__APPLE__) - #endif +#endif this->UpdateChannel(wakeup_channel_); } diff --git a/src/net/Pipe.cpp b/src/net/Pipe.cpp index 26a5c62..8d4d9c8 100644 --- a/src/net/Pipe.cpp +++ b/src/net/Pipe.cpp @@ -55,11 +55,11 @@ bool Pipe::Create() SocketUtil::SetNonBlock(pipe_fd_[0]); SocketUtil::SetNonBlock(pipe_fd_[1]); -#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(ANDROID) +#elif defined(__linux) || defined(__linux__) || defined(__FreeBSD__) if (pipe2(pipe_fd_, O_NONBLOCK | O_CLOEXEC) < 0) { return false; } -#elif defined(__APPLE__) +#elif defined(__APPLE__) || defined(ANDROID) if(pipe(pipe_fd_) < 0) return false; if(fcntl(pipe_fd_[0],F_SETFL,O_NONBLOCK | O_CLOEXEC) < 0) diff --git a/src/net/Socket.h b/src/net/Socket.h index a693e90..d3d099f 100644 --- a/src/net/Socket.h +++ b/src/net/Socket.h @@ -42,6 +42,13 @@ #endif +#if defined(ANDROID) + #include + #ifndef MODULE_NAME + #define MODULE_NAME "RTSPSERVER" + #endif +#endif + #include #include diff --git a/src/net/SocketUtil.cpp b/src/net/SocketUtil.cpp index 6386459..1cd4bfe 100644 --- a/src/net/SocketUtil.cpp +++ b/src/net/SocketUtil.cpp @@ -101,7 +101,11 @@ void SocketUtil::SetSendBufSize(SOCKET sockfd, int size) void SocketUtil::SetRecvBufSize(SOCKET sockfd, int size) { if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size)) < 0) + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "SocketUtil: Error setting SO_RCVBUF to %d",size); + #else std::cerr << "Error setting SO_RCVBUF to " << size << std::endl; + #endif } int SocketUtil::GetSendBufSize(SOCKET sockfd) @@ -109,7 +113,11 @@ int SocketUtil::GetSendBufSize(SOCKET sockfd) int optval; socklen_t optlen = sizeof(optval); if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "SocketUtil: Error getting SO_SNDBUF"); + #else std::cerr << "Error getting SO_SNDBUF " << std::endl; + #endif return optval; } @@ -118,7 +126,11 @@ int SocketUtil::GetRecvBufSize(SOCKET sockfd) int optval; socklen_t optlen = sizeof(optval); if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &optval, &optlen) < 0) + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "SocketUtil: Error getting SO_RCVBUF"); + #else std::cerr << "Error getting SO_RCVBUF " << std::endl; + #endif return optval; } diff --git a/src/net/TcpConnection.cpp b/src/net/TcpConnection.cpp index 7ee7850..5d66d2e 100644 --- a/src/net/TcpConnection.cpp +++ b/src/net/TcpConnection.cpp @@ -37,7 +37,11 @@ void TcpConnection::Send(std::shared_ptr data, uint32_t size) if (!is_closed_) { mutex_.lock(); if (!write_buffer_->Append(data, size)) +#if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "TcpConnection: write_buffer failed..."); +#else std::cerr << "write_buffer failed" << std::endl; +#endif mutex_.unlock(); this->HandleWrite(); @@ -49,7 +53,11 @@ void TcpConnection::Send(const char *data, uint32_t size) if (!is_closed_) { mutex_.lock(); if ( !write_buffer_->Append(data, size)) +#if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "TcpConnection: write_buffer failed..."); +#else std::cerr << "write_buffer failed" << std::endl; +#endif mutex_.unlock(); this->HandleWrite(); @@ -73,7 +81,7 @@ void TcpConnection::HandleRead() if (is_closed_) { return; } - + int ret = read_buffer_->Read(channel_->GetSocket()); if (ret <= 0) { this->Close(); @@ -95,7 +103,7 @@ void TcpConnection::HandleWrite() if (is_closed_) { return; } - + //std::lock_guard lock(mutex_); if (!mutex_.try_lock()) { return; @@ -136,11 +144,11 @@ void TcpConnection::Close() if (close_cb_) { close_cb_(shared_from_this()); - } + } if (disconnect_cb_) { disconnect_cb_(shared_from_this()); - } + } } } diff --git a/src/net/TcpServer.cpp b/src/net/TcpServer.cpp index 3c53d25..128dc9c 100644 --- a/src/net/TcpServer.cpp +++ b/src/net/TcpServer.cpp @@ -2,7 +2,7 @@ #include "Acceptor.h" #include "EventLoop.h" #include "Logger.h" -#include +#include using namespace xop; using namespace std; @@ -53,7 +53,7 @@ bool TcpServer::Start(std::string ip, uint16_t port) void TcpServer::Stop() { - if (is_started_) { + if (is_started_) { mutex_.lock(); for (auto iter : connections_) { iter.second->Disconnect(); @@ -69,11 +69,14 @@ void TcpServer::Stop() break; } } - } + } } TcpConnection::Ptr TcpServer::OnConnect(SOCKET sockfd) { + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "TcpServer: received connect request..."); + #endif return std::make_shared(event_loop_->GetTaskScheduler().get(), sockfd); } diff --git a/src/xop/RtpConnection.cpp b/src/xop/RtpConnection.cpp index cbab596..37d8cc4 100644 --- a/src/xop/RtpConnection.cpp +++ b/src/xop/RtpConnection.cpp @@ -88,7 +88,7 @@ bool RtpConnection::SetupRtpOverUdp(MediaChannelId channel_id, uint16_t rtp_port if (n == 10) { return false; } - + local_rtp_port_[channel_id] = rd() & 0xfffe; local_rtcp_port_[channel_id] =local_rtp_port_[channel_id] + 1; @@ -109,8 +109,11 @@ bool RtpConnection::SetupRtpOverUdp(MediaChannelId channel_id, uint16_t rtp_port } SocketUtil::SetSendBufSize(rtpfd_[channel_id], 200*1024); +#if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "SocketUtil: SendBufSize is %d",SocketUtil::GetSendBufSize(rtpfd_[channel_id])); +#else std::cerr << "SendBufSize is " << SocketUtil::GetSendBufSize(rtpfd_[channel_id]) << std::endl; - +#endif peer_rtp_addr_[channel_id].sin_family = AF_INET; peer_rtp_addr_[channel_id].sin_addr.s_addr = peer_addr_.sin_addr.s_addr; peer_rtp_addr_[channel_id].sin_port = htons(media_channel_info_[channel_id].rtp_port); @@ -132,7 +135,7 @@ bool RtpConnection::SetupRtpOverMulticast(MediaChannelId channel_id, std::string if (n == 10) { return false; } - + local_rtp_port_[channel_id] = rd() & 0xfffe; rtpfd_[channel_id] = ::socket(AF_INET, SOCK_DGRAM, 0); if (!SocketUtil::Bind(rtpfd_[channel_id], "0.0.0.0", local_rtp_port_[channel_id])) { @@ -204,7 +207,7 @@ string RtpConnection::GetRtpInfo(const std::string& rtsp_url) if (media_channel_info_[chn].is_setup) { if (num_channel != 0) { snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ","); - } + } snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "url=%s/track%d;seq=0;rtptime=%u", @@ -235,11 +238,11 @@ void RtpConnection::SetRtpHeader(MediaChannelId channel_id, RtpPacket pkt) } int RtpConnection::SendRtpPacket(MediaChannelId channel_id, RtpPacket pkt) -{ +{ if (is_closed_) { return -1; } - + auto conn = rtsp_connection_.lock(); if (!conn) { return -1; @@ -248,14 +251,14 @@ int RtpConnection::SendRtpPacket(MediaChannelId channel_id, RtpPacket pkt) bool ret = rtsp_conn->task_scheduler_->AddTriggerEvent([this, channel_id, pkt] { this->SetFrameType(pkt.type); this->SetRtpHeader(channel_id, pkt); - if((media_channel_info_[channel_id].is_play || media_channel_info_[channel_id].is_record) && has_key_frame_ ) { + if((media_channel_info_[channel_id].is_play || media_channel_info_[channel_id].is_record) && has_key_frame_ ) { if(transport_mode_ == RTP_OVER_TCP) { SendRtpOverTcp(channel_id, pkt); } else { SendRtpOverUdp(channel_id, pkt); } - + //media_channel_info_[channel_id].octetCount += pkt.size; //media_channel_info_[channel_id].packetCount += 1; } @@ -285,8 +288,8 @@ int RtpConnection::SendRtpOverUdp(MediaChannelId channel_id, RtpPacket pkt) { int ret = sendto(rtpfd_[channel_id], (const char*)pkt.data.get()+4, pkt.size-4, 0, (struct sockaddr *)&(peer_rtp_addr_[channel_id]), sizeof(struct sockaddr_in)); - - if(ret < 0) { + + if(ret < 0) { Teardown(); return -1; } diff --git a/src/xop/RtspConnection.cpp b/src/xop/RtspConnection.cpp index 4ce502a..e0503dc 100644 --- a/src/xop/RtspConnection.cpp +++ b/src/xop/RtspConnection.cpp @@ -105,7 +105,11 @@ bool RtspConnection::HandleRtspRequest(BufferReader& buffer) string str(buffer.Peek(), buffer.ReadableBytes()); if (str.find("rtsp") != string::npos || str.find("RTSP") != string::npos) { - std::cout << str << std::endl; + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection: %s",str.c_str()); + #else + std::cout << str << std::endl; + #endif } #endif @@ -159,7 +163,11 @@ bool RtspConnection::HandleRtspResponse(BufferReader& buffer) #if RTSP_DEBUG string str(buffer.Peek(), buffer.ReadableBytes()); if (str.find("rtsp") != string::npos || str.find("RTSP") != string::npos) { - cout << str << endl; + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection: %s",str.c_str()); + #else + cout << str << endl; + #endif } #endif @@ -196,7 +204,11 @@ bool RtspConnection::HandleRtspResponse(BufferReader& buffer) void RtspConnection::SendRtspMessage(std::shared_ptr buf, uint32_t size) { #if RTSP_DEBUG - cout << buf.get() << endl; + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection: %s",buf.get()); + #else + cout << buf.get() << endl; + #endif #endif this->Send(buf, size); diff --git a/src/xop/RtspServer.cpp b/src/xop/RtspServer.cpp index b7bcf27..64a9a53 100644 --- a/src/xop/RtspServer.cpp +++ b/src/xop/RtspServer.cpp @@ -14,7 +14,7 @@ RtspServer::RtspServer(EventLoop* loop) RtspServer::~RtspServer() { - + } std::shared_ptr RtspServer::Create(xop::EventLoop* loop) @@ -31,7 +31,7 @@ MediaSessionId RtspServer::AddSession(MediaSession* session) return 0; } - std::shared_ptr media_session(session); + std::shared_ptr media_session(session); MediaSessionId sessionId = media_session->GetMediaSessionId(); rtsp_suffix_map_.emplace(std::move(media_session->GetRtspUrlSuffix()), sessionId); media_sessions_.emplace(sessionId, std::move(media_session)); @@ -98,7 +98,9 @@ bool RtspServer::PushFrame(MediaSessionId session_id, MediaChannelId channel_id, } TcpConnection::Ptr RtspServer::OnConnect(SOCKET sockfd) -{ +{ + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspServer: received connect request..."); + #endif return std::make_shared(shared_from_this(), event_loop_->GetTaskScheduler().get(), sockfd); } - diff --git a/src/xop/rtsp.h b/src/xop/rtsp.h index df9d7e4..758a629 100644 --- a/src/xop/rtsp.h +++ b/src/xop/rtsp.h @@ -13,6 +13,13 @@ #include "net/Socket.h" #include "net/Timer.h" +#if defined(ANDROID) + #include + #ifndef MODULE_NAME + #define MODULE_NAME "RTSPSERVER" + #endif +#endif + namespace xop { From 64ba5e6e812fb761b5593bd529373507f5166f76 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Tue, 11 May 2021 13:03:43 +0200 Subject: [PATCH 05/21] digest auth for pusher --- example/rtsp_pusher.cpp | 228 +++++++++++++++++++++--- src/xop/Authenticator.h | 10 +- src/xop/DigestAuthenticator.cpp | 94 +++++++++- src/xop/DigestAuthenticator.h | 2 + src/xop/MediaSession.cpp | 27 ++- src/xop/RtspConnection.cpp | 132 ++++++++++---- src/xop/RtspConnection.h | 16 +- src/xop/RtspMessage.cpp | 297 ++++++++++++++++++++++---------- src/xop/RtspMessage.h | 30 +++- src/xop/RtspPusher.cpp | 134 +++++++------- 10 files changed, 742 insertions(+), 228 deletions(-) diff --git a/example/rtsp_pusher.cpp b/example/rtsp_pusher.cpp index baf30bf..ce21ea4 100755 --- a/example/rtsp_pusher.cpp +++ b/example/rtsp_pusher.cpp @@ -1,35 +1,92 @@ -// RTSP Pusher +// RTSP Pusher #include "xop/RtspPusher.h" +#include "xop/DigestAuthenticator.h" #include "net/Timer.h" #include #include #include #include -#define PUSH_TEST "rtsp://10.11.165.203:554/test" +#include "md5/md5.hpp" -void snedFrameThread(xop::RtspPusher* rtspPusher); +// #define PUSH_TEST "rtsp://10.11.165.203:554/test" + +class H264File +{ +public: + H264File(int buf_size=500000); + ~H264File(); + + bool Open(const char *path); + void Close(); + + bool IsOpened() const + { return (m_file != NULL); } + + int ReadFrame(char* in_buf, int in_buf_size, bool* end); + +private: + FILE *m_file = NULL; + char *m_buf = NULL; + int m_buf_size = 0; + int m_bytes_used = 0; + int m_count = 0; +}; + +void sendFrameThread(xop::RtspPusher* rtspPusher, H264File* h264_file); int main(int argc, char **argv) { + if(argc != 2) { + printf("Usage: %s test.h264 \n", argv[0]); + return 0; + } + + H264File h264_file; + if(!h264_file.Open(argv[1])) { + printf("Open %s failed.\n", argv[1]); + return 0; + } + std::shared_ptr event_loop(new xop::EventLoop()); std::shared_ptr rtsp_pusher = xop::RtspPusher::Create(event_loop.get()); xop::MediaSession *session = xop::MediaSession::CreateNew(); session->AddSource(xop::channel_0, xop::H264Source::CreateNew()); - session->AddSource(xop::channel_1, xop::AACSource::CreateNew(44100, 2, false)); + // session->AddSource(xop::channel_1, xop::AACSource::CreateNew(44100, 2, false)); rtsp_pusher->AddSession(session); - if (rtsp_pusher->OpenUrl(PUSH_TEST, 3000) < 0) { - std::cout << "Open " << PUSH_TEST << " failed." << std::endl; + // To: "5b47756573745d2047656e65726f757320636f617469" ;tag=9dd61ff61e802d8e2bef5f14621ef3c2.cc43 + + std::string serverIP("54.155.36.131"); + uint16_t port = 8554; + std::string channel("live/myStream?playid=1&replaces=609a63c11386cc001241d89a@integrations.visocon.com"); + std::string username("visoconEyesOn"); + std::string password("VdtxeQnwIaZmaQLc"); +/* + std::string serverIP("192.168.0.32"); + uint16_t port = 8554; + std::string channel("live"); + std::string username(""); + std::string password(""); + */ + if(username.size() && password.size()) + { + std::shared_ptr auth = std::shared_ptr(new xop::DigestAuthenticator("-_-", username, password)); // "visocon.rtsp" + rtsp_pusher->SetAuthenticator(auth); + } + + std::string connectString = "rtsp://" + serverIP + ":" + std::to_string(port) + "/" + channel; + if (rtsp_pusher->OpenUrl(connectString.c_str(), 3000) < 0) { + std::cout << "Open " << connectString.c_str() << " failed." << std::endl; getchar(); return 0; } - std::cout << "Push stream to " << PUSH_TEST << " ..." << std::endl; + std::cout << "Push stream to " << connectString.c_str() << " ..." << std::endl; - std::thread thread(snedFrameThread, rtsp_pusher.get()); + std::thread thread(sendFrameThread, rtsp_pusher.get(),&h264_file); thread.detach(); while (1) { @@ -40,22 +97,29 @@ int main(int argc, char **argv) return 0; } -void snedFrameThread(xop::RtspPusher* rtsp_pusher) +void sendFrameThread(xop::RtspPusher* rtsp_pusher, H264File* h264_file) { while(rtsp_pusher->IsConnected()) { - { -/* - //获取一帧 H264, 打包 - xop::AVFrame videoFrame; - //videoFrame.size = video frame size; // 视频帧大小 - videoFrame.timestamp = xop::H264Source::GetTimestamp(); // 时间戳, 建议使用编码器提供的时间戳 - videoFrame.buffer.resize(frame_size); - videoFrame.type = 0; - // memcpy(videoFrame.buffer.data(), frame_buf.get(), frame_size); - - rtsp_pusher->PushFrame(xop::channel_0, videoFrame); //推流到服务器, 接口线程安全 -*/ + int buf_size = 2000000; + std::unique_ptr frame_buf(new uint8_t[buf_size]); + + bool end_of_frame = false; + int frame_size = h264_file->ReadFrame((char*)frame_buf.get(), buf_size, &end_of_frame); + if(frame_size > 0) { + xop::AVFrame videoFrame; + videoFrame.type = 0; + auto time_point = std::chrono::time_point_cast(std::chrono::steady_clock::now()); + int64_t tp = (int64_t)((time_point.time_since_epoch().count() + 500) / 1000 * 90 ); + videoFrame.timestamp = xop::H264Source::GetTimestamp(); // tp; + //videoFrame.buffer.reset(new uint8_t[videoFrame.size]); + //memcpy(videoFrame.buffer.get(), frame_buf.get(), videoFrame.size); + videoFrame.buffer.resize(frame_size); + memcpy(videoFrame.buffer.data(), frame_buf.get(), frame_size); + rtsp_pusher->PushFrame(xop::channel_0, videoFrame); + } + else { + break; } { @@ -71,6 +135,126 @@ void snedFrameThread(xop::RtspPusher* rtsp_pusher) */ } - xop::Timer::Sleep(1); + xop::Timer::Sleep(40); + } +} + +H264File::H264File(int buf_size) + : m_buf_size(buf_size) +{ + m_buf = new char[m_buf_size]; +} + +H264File::~H264File() +{ + delete m_buf; +} + +bool H264File::Open(const char *path) +{ + m_file = fopen(path, "rb"); + if(m_file == NULL) { + return false; + } + + return true; +} + +void H264File::Close() +{ + if(m_file) { + fclose(m_file); + m_file = NULL; + m_count = 0; + m_bytes_used = 0; + } +} + +int H264File::ReadFrame(char* in_buf, int in_buf_size, bool* end) +{ + if(m_file == NULL) { + return -1; + } + + int bytes_read = (int)fread(m_buf, 1, m_buf_size, m_file); + if(bytes_read == 0) { + fseek(m_file, 0, SEEK_SET); + m_count = 0; + m_bytes_used = 0; + bytes_read = (int)fread(m_buf, 1, m_buf_size, m_file); + if(bytes_read == 0) { + this->Close(); + return -1; + } + } + + bool is_find_start = false, is_find_end = false; + int i = 0, start_code = 3; + *end = false; + + for (i=0; i0) { + flag = is_find_end = true; + i = bytes_read; + *end = true; + } + + if(!is_find_start || !is_find_end) { + this->Close(); + return -1; + } + + int size = (i<=in_buf_size ? i : in_buf_size); + memcpy(in_buf, m_buf, size); + + if(!flag) { + m_count += 1; + m_bytes_used += i; + } + else { + m_count = 0; + m_bytes_used = 0; + } + + fseek(m_file, m_bytes_used, SEEK_SET); + return size; } diff --git a/src/xop/Authenticator.h b/src/xop/Authenticator.h index 63c0d40..714bdcd 100644 --- a/src/xop/Authenticator.h +++ b/src/xop/Authenticator.h @@ -3,6 +3,7 @@ #include #include "RtspMessage.h" +#include "net/BufferReader.h" namespace xop { @@ -13,8 +14,13 @@ class Authenticator Authenticator() {}; virtual ~Authenticator() {}; - virtual bool Authenticate(std::shared_ptr request, std::string &nonce) = 0; - virtual size_t GetFailedResponse(std::shared_ptr request, std::shared_ptr buf, size_t size) = 0; + virtual std::string GetUsername() const = 0; + virtual std::string GetRealm() const = 0; + + virtual bool Authenticate(std::shared_ptr request, std::string &nonce) = 0; + virtual bool HandleUnauthorized(BufferReader* buffer, std::string& nonce, bool& unauthorized) = 0; + virtual std::string GetResponse(std::string nonce, std::string cmd, std::string url) = 0; + virtual size_t GetFailedResponse(std::shared_ptr request, std::shared_ptr buf, size_t size) = 0; private: diff --git a/src/xop/DigestAuthenticator.cpp b/src/xop/DigestAuthenticator.cpp index 7aae4cf..36e6b4a 100644 --- a/src/xop/DigestAuthenticator.cpp +++ b/src/xop/DigestAuthenticator.cpp @@ -1,5 +1,7 @@ #include "DigestAuthenticator.h" -#include "md5/md5.hpp" +#include "md5/md5.hpp" + +#include using namespace xop; @@ -8,7 +10,11 @@ DigestAuthenticator::DigestAuthenticator(std::string realm, std::string username , username_(username) , password_(password) { - + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator Constructor"); + #else + std::cout << "DigestAuthenticator Constructor" << std::endl; + #endif } DigestAuthenticator::~DigestAuthenticator() @@ -18,6 +24,12 @@ DigestAuthenticator::~DigestAuthenticator() std::string DigestAuthenticator::GetNonce() { + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator GetNonce"); + #else + std::cout << "DigestAuthenticator GetNonce" << std::endl; + #endif + return md5::generate_nonce(); } @@ -28,9 +40,66 @@ std::string DigestAuthenticator::GetResponse(std::string nonce, std::string cmd, auto hex1 = md5::md5_hash_hex(username_ + ":" + realm_ + ":" + password_); auto hex2 = md5::md5_hash_hex(cmd + ":" + url); auto response = md5::md5_hash_hex(hex1 + ":" + nonce + ":" + hex2); + + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator GetResponse"); + #else + std::cout << "DigestAuthenticator GetResponse" << std::endl; + #endif + + return response; } +bool parseParam(std::string& line, std::string param, std::string& value) +{ + size_t idx = line.find(param); + if(idx != line.npos) + { + int cnt1 = idx + param.size(); + while(line[cnt1++] != '\"'); + int cnt2 = cnt1+1; + while(line[cnt2++] != '\"'); + value = line.substr(cnt1, cnt2 - cnt1 - 1); + std::cout << "Value = " << value << std::endl; + return true; + } + return false; +} + +bool DigestAuthenticator::HandleUnauthorized(BufferReader* buffer, std::string& nonce, bool& unauthorized) +{ + bool complete = false; + unauthorized = false; + // TRY PARSE STUFF OF THIS FORM: + // "RTSP/1.0 401 Unauthorized" + // "Content-Length: 91" + // "Content-Type: text/html" + // "WWW-Authenticate: Digest realm=\"visocon.rtsp\" charset=\"UTF-8\" nonce=\"761ca587865b0c3ba7af2a0e95876833\"" + while(!complete) + { + const char* firstCrlf = buffer->FindFirstCrlf(); + const char* start = buffer->Peek(); + if(firstCrlf != nullptr) + { + std::string line(start, firstCrlf); + if(line.find("Unauthorized") != line.npos) + unauthorized = true; + + if(line.find("WWW-Authenticate") != line.npos && line.find("Digest") != line.npos) + { + if(parseParam(line, "realm", realm_) && + parseParam(line, "nonce", nonce)) + complete = true; + } + buffer->RetrieveUntil(firstCrlf + 2); + } + else + break; + } + return complete; +} + bool DigestAuthenticator::Authenticate( std::shared_ptr rtsp_request, std::string &nonce) @@ -39,10 +108,22 @@ bool DigestAuthenticator::Authenticate( std::string url = rtsp_request->GetRtspUrl(); if (nonce.size() > 0 && (GetResponse(nonce, cmd, url) == rtsp_request->GetAuthResponse())) { + + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator Authenticate success %s - %s - %s", cmd, url.c_str(), nonce.c_str()); + #else + std::cout << "DigestAuthenticator Authenticate success" << cmd << " - " << url.c_str() << " - " << nonce.c_str() << std::endl; + #endif + return true; } else { -#if 0 -#endif + + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator Authenticate failed %s - %s - %s", cmd, url.c_str(), nonce.c_str()); + #else + std::cout << "DigestAuthenticator Authenticate failed" << cmd << " - " << url.c_str() << " - " << nonce.c_str() << std::endl; + #endif + return false; } } @@ -53,5 +134,10 @@ size_t DigestAuthenticator::GetFailedResponse( size_t size) { std::string nonce = md5::generate_nonce(); +#if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator GetFailedResponse %s - %s - %s", buf.get(), realm_.c_str(), nonce.c_str()); +#else + std::cout << "DigestAuthenticator GetFailedResponse" << buf.get() << " - " << realm_.c_str() << " - " << nonce.c_str() << std::endl; +#endif return rtsp_request->BuildUnauthorizedRes(buf.get(), size, realm_.c_str(), nonce.c_str()); } diff --git a/src/xop/DigestAuthenticator.h b/src/xop/DigestAuthenticator.h index a584cd1..e3d20f3 100644 --- a/src/xop/DigestAuthenticator.h +++ b/src/xop/DigestAuthenticator.h @@ -30,6 +30,8 @@ class DigestAuthenticator : public Authenticator std::string GetNonce(); std::string GetResponse(std::string nonce, std::string cmd, std::string url); + bool HandleUnauthorized(BufferReader* buffer,std::string& nonce, bool& unauthorized); + bool Authenticate(std::shared_ptr request, std::string &nonce); size_t GetFailedResponse(std::shared_ptr request, std::shared_ptr buf, size_t size); diff --git a/src/xop/MediaSession.cpp b/src/xop/MediaSession.cpp index 2282eb6..d715130 100644 --- a/src/xop/MediaSession.cpp +++ b/src/xop/MediaSession.cpp @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-9-30 #include "MediaSession.h" @@ -139,13 +139,27 @@ std::string MediaSession::GetSdpMessage(std::string ip, std::string session_name } char buf[2048] = {0}; - +/* + snprintf(buf, sizeof(buf), + "v=0\r\n" + "o=- 0 0 IN IP4 127.0.0.1\r\n" + "s=No Name\r\n" + "c=IN IP4 54.155.36.131\r\n" + "t=0 0\r\n" + "a=tool:libavformat 58.76.100\r\n" + "m=video 0 RTP/AVP 96\r\n" + "a=rtpmap:96 H264/90000\r\n" + "a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6yyAeBr8v/gIgAiIgAAAwACAAADAHgeMGSQ,aOvDyyLA; profile-level-id=64001F\r\n" + "a=control:streamid=0\r\n"); +*/ + snprintf(buf, sizeof(buf), "v=0\r\n" "o=- 9%ld 1 IN IP4 %s\r\n" "t=0 0\r\n" "a=control:*\r\n" , - (long)std::time(NULL), ip.c_str()); + (long)std::time(NULL), + ip.c_str()); if(session_name != "") { snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), @@ -175,16 +189,19 @@ std::string MediaSession::GetSdpMessage(std::string ip, std::string session_name "%s\r\n", media_sources_[chn]->GetMediaDescription(0).c_str()); } + //snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), + // "c=IN IP4 54.155.36.131\r\n"); snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s\r\n", media_sources_[chn]->GetAttribute().c_str()); snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), - "a=control:track%d\r\n", chn); + // "a=control:track%d\r\n", chn); + "a=control:streamid=%d\r\n", chn); } } - + sdp_ = buf; return sdp_; } diff --git a/src/xop/RtspConnection.cpp b/src/xop/RtspConnection.cpp index e0503dc..0815793 100644 --- a/src/xop/RtspConnection.cpp +++ b/src/xop/RtspConnection.cpp @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-6-10 #include "RtspConnection.h" @@ -7,8 +7,8 @@ #include "MediaSource.h" #include "net/SocketUtil.h" -#define USER_AGENT "-_-" -#define RTSP_DEBUG 0 +#define USER_AGENT "Lavf57.83.100" //"-_-" +#define RTSP_DEBUG 1 #define MAX_RTSP_MESSAGE_SIZE 2048 using namespace xop; @@ -22,6 +22,13 @@ RtspConnection::RtspConnection(std::shared_ptr rtsp, TaskScheduler *task_s , rtsp_request_(new RtspRequest) , rtsp_response_(new RtspResponse) { + + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspRequest Constructor"); + #else + std::cout << "RtspConnection Constructor" << std::endl; + #endif + this->SetReadCallback([this](std::shared_ptr conn, xop::BufferReader& buffer) { return this->OnRead(buffer); }); @@ -106,9 +113,9 @@ bool RtspConnection::HandleRtspRequest(BufferReader& buffer) if (str.find("rtsp") != string::npos || str.find("RTSP") != string::npos) { #if defined(ANDROID) - __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection: %s",str.c_str()); + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::HandleRtspRequest: %s",str.c_str()); #else - std::cout << str << std::endl; + std::cout << "RtspConnection::HandleRtspRequest: " << str << std::endl; #endif } #endif @@ -125,26 +132,26 @@ bool RtspConnection::HandleRtspRequest(BufferReader& buffer) switch (method) { - case RtspRequest::OPTIONS: - HandleCmdOption(); - break; - case RtspRequest::DESCRIBE: - HandleCmdDescribe(); - break; - case RtspRequest::SETUP: - HandleCmdSetup(); - break; - case RtspRequest::PLAY: - HandleCmdPlay(); - break; - case RtspRequest::TEARDOWN: - HandleCmdTeardown(); - break; - case RtspRequest::GET_PARAMETER: - HandleCmdGetParamter(); - break; - default: - break; + case RtspRequest::OPTIONS: + HandleCmdOption(); + break; + case RtspRequest::DESCRIBE: + HandleCmdDescribe(); + break; + case RtspRequest::SETUP: + HandleCmdSetup(); + break; + case RtspRequest::PLAY: + HandleCmdPlay(); + break; + case RtspRequest::TEARDOWN: + HandleCmdTeardown(); + break; + case RtspRequest::GET_PARAMETER: + HandleCmdGetParamter(); + break; + default: + break; } if (rtsp_request_->GotAll()) { @@ -164,13 +171,12 @@ bool RtspConnection::HandleRtspResponse(BufferReader& buffer) string str(buffer.Peek(), buffer.ReadableBytes()); if (str.find("rtsp") != string::npos || str.find("RTSP") != string::npos) { #if defined(ANDROID) - __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection: %s",str.c_str()); + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::HandleRtspResponse: \n%s",str.c_str()); #else - cout << str << endl; + cout << "RtspConnection::HandleRtspResponse: " << endl << str << endl; #endif } #endif - if (rtsp_response_->ParseResponse(&buffer)) { RtspResponse::Method method = rtsp_response_->GetMethod(); switch (method) @@ -195,9 +201,50 @@ bool RtspConnection::HandleRtspResponse(BufferReader& buffer) } } else { + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::HandleRtspResponse: ParseResponse failed!"); + #else + cout << "RtspConnection::HandleRtspResponse: ParseResponse failed!" << endl; + #endif + //========================================================================= + if (conn_mode_ == RTSP_PUSHER) + { + // check if unauthorized + // if yes, try fix it with authenticator + // else just return false + + // parse auth info + if (authenticator_!=nullptr) + { + bool unauthorized = false; + if(authenticator_->HandleUnauthorized(&buffer, _nonce, unauthorized)) + { + if(unauthorized) + { + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::HandleRtspResponse: Resending Options!"); + #else + cout << "RtspConnection::HandleRtspResponse: Resending Options!" << endl; + #endif + rtsp_response_->SetCSeq(rtsp_response_->GetCSeq() + 1); + SendOptions(RtspConnection::RTSP_PUSHER); + //task_scheduler_->AddTriggerEvent([this]() { + // SendOptions(RtspConnection::RTSP_PUSHER); + //}); + return true; + } + } + } + } return false; + //========================================================================= } + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::HandleRtspResponse: ParseResponse ok!"); + #else + cout << "RtspConnection::HandleRtspResponse: ParseResponse ok!" << endl; + #endif return true; } @@ -205,9 +252,9 @@ void RtspConnection::SendRtspMessage(std::shared_ptr buf, uint32_t size) { #if RTSP_DEBUG #if defined(ANDROID) - __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection: %s",buf.get()); + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::SendRtspMessage: \n%s",buf.get()); #else - cout << buf.get() << endl; + cout << "RtspConnection::SendRtspMessage: " << endl << buf.get() << endl; #endif #endif @@ -423,6 +470,12 @@ void RtspConnection::HandleCmdGetParamter() bool RtspConnection::HandleAuthentication() { + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspConnection HandleAuthentication"); + #else + std::cout << "RtspConnection HandleAuthentication" << std::endl; + #endif + if (authenticator_ != nullptr && !has_auth_) { if (authenticator_->Authenticate(rtsp_request_, _nonce)) { has_auth_ = true; @@ -454,7 +507,14 @@ void RtspConnection::SendOptions(ConnectionMode mode) rtsp_response_->SetRtspUrl(rtsp->GetRtspUrl().c_str()); std::shared_ptr req(new char[2048], std::default_delete()); - int size = rtsp_response_->BuildOptionReq(req.get(), 2048); + int size = rtsp_response_->BuildOptionReq(req.get(), 2048, _nonce, authenticator_.get()); + + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::SendOptions:"); + #else + cout << "RtspConnection::SendOptions: " << endl; + #endif + SendRtspMessage(req, size); } @@ -491,14 +551,14 @@ void RtspConnection::SendAnnounce() } std::shared_ptr req(new char[4096], std::default_delete()); - int size = rtsp_response_->BuildAnnounceReq(req.get(), 4096, sdp.c_str()); + int size = rtsp_response_->BuildAnnounceReq(req.get(), 4096, sdp.c_str(), _nonce, authenticator_.get()); SendRtspMessage(req, size); } void RtspConnection::SendDescribe() { std::shared_ptr req(new char[2048], std::default_delete()); - int size = rtsp_response_->BuildDescribeReq(req.get(), 2048); + int size = rtsp_response_->BuildDescribeReq(req.get(), 2048, _nonce, authenticator_.get()); SendRtspMessage(req, size); } @@ -520,14 +580,14 @@ void RtspConnection::SendSetup() if (media_session->GetMediaSource(channel_0) && !rtp_conn_->IsSetup(channel_0)) { rtp_conn_->SetupRtpOverTcp(channel_0, 0, 1); - size = rtsp_response_->BuildSetupTcpReq(buf.get(), 2048, channel_0); + size = rtsp_response_->BuildSetupTcpReq(buf.get(), 2048, channel_0, _nonce, authenticator_.get()); } else if (media_session->GetMediaSource(channel_1) && !rtp_conn_->IsSetup(channel_1)) { rtp_conn_->SetupRtpOverTcp(channel_1, 2, 3); - size = rtsp_response_->BuildSetupTcpReq(buf.get(), 2048, channel_1); + size = rtsp_response_->BuildSetupTcpReq(buf.get(), 2048, channel_1, _nonce, authenticator_.get()); } else { - size = rtsp_response_->BuildRecordReq(buf.get(), 2048); + size = rtsp_response_->BuildRecordReq(buf.get(), 2048, _nonce, authenticator_.get()); } SendRtspMessage(buf, size); diff --git a/src/xop/RtspConnection.h b/src/xop/RtspConnection.h index 8299c03..cc5f7dc 100644 --- a/src/xop/RtspConnection.h +++ b/src/xop/RtspConnection.h @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-6-8 #ifndef _RTSP_CONNECTION_H @@ -75,6 +75,20 @@ class RtspConnection : public TcpConnection int GetId() const { return task_scheduler_->GetId(); } + std::string GetNonce() const + { return _nonce; } + void SetNonce(std::string nonce) + { _nonce = nonce; } + + uint32_t GetCseq() const + { + return rtsp_response_->GetCSeq(); + } + void SetCseq(uint32_t cseq) + { + rtsp_response_->SetCSeq(cseq); + } + bool IsPlay() const { return conn_state_ == START_PLAY; } diff --git a/src/xop/RtspMessage.cpp b/src/xop/RtspMessage.cpp index 8df851d..ab63b21 100644 --- a/src/xop/RtspMessage.cpp +++ b/src/xop/RtspMessage.cpp @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-5-16 #if defined(WIN32) || defined(_WIN32) @@ -8,8 +8,11 @@ #endif #include "RtspMessage.h" +#include "DigestAuthenticator.h" #include "media.h" +#include + using namespace std; using namespace xop; @@ -19,7 +22,7 @@ bool RtspRequest::ParseRequest(BufferReader *buffer) method_ = RTCP; return true; } - + bool ret = true; while(1) { if(state_ == kParseRequestLine) { @@ -32,10 +35,10 @@ bool RtspRequest::ParseRequest(BufferReader *buffer) if (state_ == kParseHeadersLine) { continue; - } + } else { break; - } + } } else if(state_ == kParseHeadersLine) { const char* lastCrlf = buffer->FindLastCrlf(); @@ -62,7 +65,7 @@ bool RtspRequest::ParseRequestLine(const char* begin, const char* end) char version[64] = {0}; if(sscanf(message.c_str(), "%s %s %s", method, url, version) != 3) { - return true; + return true; } string method_str(method); @@ -125,7 +128,7 @@ bool RtspRequest::ParseHeadersLine(const char* begin, const char* end) if(!ParseCSeq(message)) { if (header_line_param_.find("cseq") == header_line_param_.end()) { return false; - } + } } if (method_ == DESCRIBE || method_ == SETUP || method_ == PLAY) { @@ -247,7 +250,7 @@ bool RtspRequest::ParseSessionId(std::string& message) uint32_t session_id = 0; if (sscanf(message.c_str() + pos, "%*[^:]: %u", &session_id) != 1) { return false; - } + } return true; } @@ -263,14 +266,14 @@ bool RtspRequest::ParseMediaChannel(std::string& message) std::size_t pos = iter->second.first.find("track1"); if (pos != std::string::npos) { channel_id_ = channel_1; - } + } } return true; } bool RtspRequest::ParseAuthorization(std::string& message) -{ +{ std::size_t pos = message.find("Authorization"); if (pos != std::string::npos) { if ((pos = message.find("response=")) != std::string::npos) { @@ -326,7 +329,7 @@ std::string RtspRequest::GetRtspUrlSuffix() const return ""; } -std::string RtspRequest::GetRtspUrlSession() const +std::string RtspRequest::GetRtspUrlSession() const { auto iter = request_line_param_.find("url_suffix"); if(iter != request_line_param_.end()) { @@ -339,7 +342,7 @@ std::string RtspRequest::GetRtspUrlSession() const return ""; } -std::string RtspRequest::GetRtspUrlQueryString() const +std::string RtspRequest::GetRtspUrlQueryString() const { auto iter = request_line_param_.find("url_suffix"); if(iter != request_line_param_.end()) { @@ -419,15 +422,15 @@ int RtspRequest::BuildDescribeRes(const char* buf, int buf_size, const char* sdp "Content-Type: application/sdp\r\n" "\r\n" "%s", - this->GetCSeq(), - (int)strlen(sdp), + this->GetCSeq(), + (int)strlen(sdp), sdp); return (int)strlen(buf); } int RtspRequest::BuildSetupMulticastRes(const char* buf, int buf_size, const char* multicast_ip, uint16_t port, uint32_t session_id) -{ +{ memset((void*)buf, 0, buf_size); snprintf((char*)buf, buf_size, "RTSP/1.0 200 OK\r\n" @@ -456,7 +459,7 @@ int RtspRequest::BuildSetupUdpRes(const char* buf, int buf_size, uint16_t rtp_ch this->GetCSeq(), this->GetRtpPort(), this->GetRtcpPort(), - rtp_chn, + rtp_chn, rtcp_chn, session_id); @@ -576,6 +579,12 @@ size_t RtspRequest::BuildUnauthorizedRes(const char *buf, size_t buf_size) size_t RtspRequest::BuildUnauthorizedRes(const char* buf, size_t buf_size, const char* realm, const char* nonce) { + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspRequest BuildUnauthorizedRes"); + #else + std::cout << "RtspRequest BuildUnauthorizedRes" << std::endl; + #endif + memset((void*)buf, 0, buf_size); snprintf((char*)buf, buf_size, "RTSP/1.0 401 Unauthorized\r\n" @@ -610,105 +619,209 @@ bool RtspResponse::ParseResponse(xop::BufferReader *buffer) return true; } -int RtspResponse::BuildOptionReq(const char* buf, int buf_size) -{ - memset((void*)buf, 0, buf_size); - snprintf((char*)buf, buf_size, - "OPTIONS %s RTSP/1.0\r\n" - "CSeq: %u\r\n" - "User-Agent: %s\r\n" - "\r\n", - rtsp_url_.c_str(), - this->GetCSeq() + 1, - user_agent_.c_str()); - +int RtspResponse::BuildOptionReq(const char* buf, int buf_size, std::string& nonce, Authenticator* auth) +{ + if(auth != nullptr && nonce.size() > 0) + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "OPTIONS %s RTSP/1.0\r\n" + "CSeq: %u\r\n" + "User-Agent: %s\r\n" + "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n" + "\r\n", + rtsp_url_.c_str(), + this->GetCSeq() + 1, + user_agent_.c_str(), + auth->GetUsername().c_str(), auth->GetRealm().c_str(), nonce.c_str(), rtsp_url_.c_str(), + auth->GetResponse(nonce, "OPTIONS", rtsp_url_.c_str()).c_str()); + } + else + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "OPTIONS %s RTSP/1.0\r\n" + "CSeq: %u\r\n" + "User-Agent: %s\r\n" + "\r\n", + rtsp_url_.c_str(), + this->GetCSeq() + 1, + user_agent_.c_str()); + } method_ = OPTIONS; return (int)strlen(buf); } -int RtspResponse::BuildAnnounceReq(const char* buf, int buf_size, const char *sdp) -{ - memset((void*)buf, 0, buf_size); - snprintf((char*)buf, buf_size, - "ANNOUNCE %s RTSP/1.0\r\n" - "Content-Type: application/sdp\r\n" - "CSeq: %u\r\n" - "User-Agent: %s\r\n" - "Session: %s\r\n" - "Content-Length: %d\r\n" - "\r\n" - "%s", - rtsp_url_.c_str(), - this->GetCSeq() + 1, - user_agent_.c_str(), - this->GetSession().c_str(), - (int)strlen(sdp), - sdp); - +int RtspResponse::BuildAnnounceReq(const char* buf, int buf_size, const char *sdp, std::string& nonce, Authenticator* auth) +{ + if(auth != nullptr && nonce.size() > 0) + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "ANNOUNCE %s RTSP/1.0\r\n" + "Content-Type: application/sdp\r\n" + "CSeq: %u\r\n" + "User-Agent: %s\r\n" + "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n" + "Session: %s\r\n" + "Content-Length: %d\r\n" + "\r\n" + "%s", + rtsp_url_.c_str(), + this->GetCSeq() + 1, + user_agent_.c_str(), + auth->GetUsername().c_str(), auth->GetRealm().c_str(), nonce.c_str(), rtsp_url_.c_str(), + auth->GetResponse(nonce, "ANNOUNCE", rtsp_url_.c_str()).c_str(), + this->GetSession().c_str(), + (int)strlen(sdp), + sdp); + } + else + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "ANNOUNCE %s RTSP/1.0\r\n" + "Content-Type: application/sdp\r\n" + "CSeq: %u\r\n" + "User-Agent: %s\r\n" + "Session: %s\r\n" + "Content-Length: %d\r\n" + "\r\n" + "%s", + rtsp_url_.c_str(), + this->GetCSeq() + 1, + user_agent_.c_str(), + this->GetSession().c_str(), + (int)strlen(sdp), + sdp); + } method_ = ANNOUNCE; return (int)strlen(buf); } -int RtspResponse::BuildDescribeReq(const char* buf, int buf_size) -{ - memset((void*)buf, 0, buf_size); - snprintf((char*)buf, buf_size, - "DESCRIBE %s RTSP/1.0\r\n" - "CSeq: %u\r\n" - "Accept: application/sdp\r\n" - "User-Agent: %s\r\n" - "\r\n", - rtsp_url_.c_str(), - this->GetCSeq() + 1, - user_agent_.c_str()); - +int RtspResponse::BuildDescribeReq(const char* buf, int buf_size, std::string& nonce, Authenticator* auth) +{ + if(auth != nullptr && nonce.size() > 0) + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "DESCRIBE %s RTSP/1.0\r\n" + "CSeq: %u\r\n" + "Accept: application/sdp\r\n" + "User-Agent: %s\r\n" + "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n" + "\r\n", + rtsp_url_.c_str(), + this->GetCSeq() + 1, + user_agent_.c_str(), + auth->GetUsername().c_str(), auth->GetRealm().c_str(), nonce.c_str(), rtsp_url_.c_str(), + auth->GetResponse(nonce, "DESCRIBE", rtsp_url_.c_str()).c_str()); + } + else + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "DESCRIBE %s RTSP/1.0\r\n" + "CSeq: %u\r\n" + "Accept: application/sdp\r\n" + "User-Agent: %s\r\n" + "\r\n", + rtsp_url_.c_str(), + this->GetCSeq() + 1, + user_agent_.c_str()); + } method_ = DESCRIBE; return (int)strlen(buf); } -int RtspResponse::BuildSetupTcpReq(const char* buf, int buf_size, int trackId) +int RtspResponse::BuildSetupTcpReq(const char* buf, int buf_size, int trackId, std::string& nonce, Authenticator* auth) { int interleaved[2] = { 0, 1 }; if (trackId == 1) { interleaved[0] = 2; interleaved[1] = 3; } - - memset((void*)buf, 0, buf_size); - snprintf((char*)buf, buf_size, - "SETUP %s/track%d RTSP/1.0\r\n" - "Transport: RTP/AVP/TCP;unicast;mode=record;interleaved=%d-%d\r\n" - "CSeq: %u\r\n" - "User-Agent: %s\r\n" - "Session: %s\r\n" - "\r\n", - rtsp_url_.c_str(), - trackId, - interleaved[0], - interleaved[1], - this->GetCSeq() + 1, - user_agent_.c_str(), - this->GetSession().c_str()); - + if(auth != nullptr && nonce.size() > 0) + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + // "SETUP %s/track%d RTSP/1.0\r\n" + "SETUP %s/streamid=%d RTSP/1.0\r\n" + "Transport: RTP/AVP/TCP;unicast;mode=record;interleaved=%d-%d\r\n" + "CSeq: %u\r\n" + "User-Agent: %s\r\n" + "Session: %s\r\n" + "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s/streamid=%d\", response=\"%s\"\r\n" + "\r\n", + rtsp_url_.c_str(), + trackId, + interleaved[0], + interleaved[1], + this->GetCSeq() + 1, + user_agent_.c_str(), + this->GetSession().c_str(), + auth->GetUsername().c_str(), auth->GetRealm().c_str(), nonce.c_str(), rtsp_url_.c_str(), trackId, + auth->GetResponse(nonce, "SETUP", (rtsp_url_ + "/streamid=" + std::to_string(trackId)).c_str()).c_str()); + } + else + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + // "SETUP %s/track%d RTSP/1.0\r\n" + "SETUP %s/streamid=%d RTSP/1.0\r\n" + "Transport: RTP/AVP/TCP;unicast;mode=record;interleaved=%d-%d\r\n" + "CSeq: %u\r\n" + "User-Agent: %s\r\n" + "Session: %s\r\n" + "\r\n", + rtsp_url_.c_str(), + trackId, + interleaved[0], + interleaved[1], + this->GetCSeq() + 1, + user_agent_.c_str(), + this->GetSession().c_str()); + } method_ = SETUP; return (int)strlen(buf); } -int RtspResponse::BuildRecordReq(const char* buf, int buf_size) -{ - memset((void*)buf, 0, buf_size); - snprintf((char*)buf, buf_size, - "RECORD %s RTSP/1.0\r\n" - "Range: npt=0.000-\r\n" - "CSeq: %u\r\n" - "User-Agent: %s\r\n" - "Session: %s\r\n" - "\r\n", - rtsp_url_.c_str(), - this->GetCSeq() + 1, - user_agent_.c_str(), - this->GetSession().c_str()); - +int RtspResponse::BuildRecordReq(const char* buf, int buf_size, std::string& nonce, Authenticator* auth) +{ + if(auth != nullptr && nonce.size() > 0) + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "RECORD %s RTSP/1.0\r\n" + "Range: npt=0.000-\r\n" + "CSeq: %u\r\n" + "User-Agent: %s\r\n" + "Session: %s\r\n" + "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n" + "\r\n", + rtsp_url_.c_str(), + this->GetCSeq() + 1, + user_agent_.c_str(), + this->GetSession().c_str(), + auth->GetUsername().c_str(), auth->GetRealm().c_str(), nonce.c_str(), rtsp_url_.c_str(), + auth->GetResponse(nonce, "RECORD", rtsp_url_.c_str()).c_str()); + } + else + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "RECORD %s RTSP/1.0\r\n" + "Range: npt=0.000-\r\n" + "CSeq: %u\r\n" + "User-Agent: %s\r\n" + "Session: %s\r\n" + "\r\n", + rtsp_url_.c_str(), + this->GetCSeq() + 1, + user_agent_.c_str(), + this->GetSession().c_str()); + } method_ = RECORD; return (int)strlen(buf); } + diff --git a/src/xop/RtspMessage.h b/src/xop/RtspMessage.h index 8f2d2ca..85f1056 100644 --- a/src/xop/RtspMessage.h +++ b/src/xop/RtspMessage.h @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-6-8 #ifndef XOP_RTSP_MESSAGE_H @@ -12,8 +12,11 @@ #include "media.h" #include "net/BufferReader.h" + + namespace xop { +class Authenticator; class RtspRequest { @@ -52,6 +55,9 @@ class RtspRequest Method GetMethod() const { return method_; } + + std::string GetMethodAsString() const + { return std::string(MethodToString[method_]); } uint32_t GetCSeq() const; @@ -118,14 +124,24 @@ class RtspResponse OPTIONS=0, DESCRIBE, ANNOUNCE, SETUP, RECORD, RTCP, NONE, }; + + const char* MethodToString[7] = + { + "OPTIONS", "DESCRIBE", "ANNOUNCE", "SETUP", "RECORD", "RTCP", + "NONE" + }; bool ParseResponse(xop::BufferReader *buffer); Method GetMethod() const { return method_; } + + std::string GetMethodAsString() const + { return std::string(MethodToString[method_]); } uint32_t GetCSeq() const { return cseq_; } + void SetCSeq(uint32_t cseq) { cseq_ = cseq; } std::string GetSession() const { return session_; } @@ -136,12 +152,12 @@ class RtspResponse void SetRtspUrl(const char *url) { rtsp_url_ = std::string(url); } - int BuildOptionReq(const char* buf, int buf_size); - int BuildDescribeReq(const char* buf, int buf_size); - int BuildAnnounceReq(const char* buf, int buf_size, const char *sdp); - int BuildSetupTcpReq(const char* buf, int buf_size, int channel); - int BuildRecordReq(const char* buf, int buf_size); - + int BuildOptionReq(const char* buf, int buf_size, std::string& nonce, Authenticator* auth = nullptr); + int BuildDescribeReq(const char* buf, int buf_size, std::string& nonce, Authenticator* auth); + int BuildAnnounceReq(const char* buf, int buf_size, const char *sdp, std::string& nonce, Authenticator* auth); + int BuildSetupTcpReq(const char* buf, int buf_size, int channel, std::string& nonce, Authenticator* auth); + int BuildRecordReq(const char* buf, int buf_size, std::string& nonce, Authenticator* auth); + private: Method method_; uint32_t cseq_ = 0; diff --git a/src/xop/RtspPusher.cpp b/src/xop/RtspPusher.cpp index 638160b..e61c00b 100644 --- a/src/xop/RtspPusher.cpp +++ b/src/xop/RtspPusher.cpp @@ -1,4 +1,4 @@ -#include "RtspPusher.h" +#include "RtspPusher.h" #include "RtspConnection.h" #include "net/Logger.h" #include "net/TcpSocket.h" @@ -45,63 +45,79 @@ int RtspPusher::OpenUrl(std::string url, int msec) { std::lock_guard lock(mutex_); - static xop::Timestamp timestamp; - int timeout = msec; - if (timeout <= 0) { - timeout = 10000; - } - - timestamp.Reset(); - - if (!this->ParseRtspUrl(url)) { - LOG_ERROR("rtsp url(%s) was illegal.\n", url.c_str()); - return -1; - } - - if (rtsp_conn_ != nullptr) { - std::shared_ptr rtspConn = rtsp_conn_; - SOCKET sockfd = rtspConn->GetSocket(); - task_scheduler_->AddTriggerEvent([sockfd, rtspConn]() { - rtspConn->Disconnect(); - }); - rtsp_conn_ = nullptr; - } - - TcpSocket tcpSocket; - tcpSocket.Create(); - if (!tcpSocket.Connect(rtsp_url_info_.ip, rtsp_url_info_.port, timeout)) - { - tcpSocket.Close(); - return -1; - } - - task_scheduler_ = event_loop_->GetTaskScheduler().get(); - rtsp_conn_.reset(new RtspConnection(shared_from_this(), task_scheduler_, tcpSocket.GetSocket())); - event_loop_->AddTriggerEvent([this]() { - rtsp_conn_->SendOptions(RtspConnection::RTSP_PUSHER); - }); - - timeout -= (int)timestamp.Elapsed(); - if (timeout < 0) { - timeout = 1000; - } - - do - { - xop::Timer::Sleep(100); - timeout -= 100; - } while (!rtsp_conn_->IsRecord() && timeout > 0); - - if (!rtsp_conn_->IsRecord()) { - std::shared_ptr rtspConn = rtsp_conn_; - SOCKET sockfd = rtspConn->GetSocket(); - task_scheduler_->AddTriggerEvent([sockfd, rtspConn]() { - rtspConn->Disconnect(); - }); - rtsp_conn_ = nullptr; - return -1; - } - + int retry = false; std::string nonce; uint32_t cseq = 0; +// while(true) +// { + static xop::Timestamp timestamp; + int timeout = msec; + if (timeout <= 0) { + timeout = 5000; + } + + timestamp.Reset(); + + if (!this->ParseRtspUrl(url)) { + LOG_ERROR("rtsp url(%s) was illegal.\n", url.c_str()); + return -1; + } + + if (rtsp_conn_ != nullptr) { + std::shared_ptr rtspConn = rtsp_conn_; + SOCKET sockfd = rtspConn->GetSocket(); + task_scheduler_->AddTriggerEvent([sockfd, rtspConn]() { + rtspConn->Disconnect(); + }); + nonce = rtsp_conn_->GetNonce(); + cseq = rtsp_conn_->GetCseq() + 1; + rtsp_conn_ = nullptr; + } + + TcpSocket tcpSocket; + tcpSocket.Create(); + if (!tcpSocket.Connect(rtsp_url_info_.ip, rtsp_url_info_.port, timeout)) + { + tcpSocket.Close(); + return -1; + } + + task_scheduler_ = event_loop_->GetTaskScheduler().get(); + rtsp_conn_.reset(new RtspConnection(shared_from_this(), task_scheduler_, tcpSocket.GetSocket())); + rtsp_conn_->SetNonce(nonce); + rtsp_conn_->SetCseq(cseq); + event_loop_->AddTriggerEvent([this]() { + rtsp_conn_->SendOptions(RtspConnection::RTSP_PUSHER); + }); + + timeout -= (int)timestamp.Elapsed(); + if (timeout < 0) { + timeout = 1000; + } + // we should check authentication status here! + do + { + xop::Timer::Sleep(100); + timeout -= 100; + } while (!rtsp_conn_->IsRecord() && timeout > 0); + + if (!rtsp_conn_->IsRecord()) { + std::shared_ptr rtspConn = rtsp_conn_; + SOCKET sockfd = rtspConn->GetSocket(); + task_scheduler_->AddTriggerEvent([sockfd, rtspConn]() { + rtspConn->Disconnect(); + }); + + // here we need to save some states + nonce = rtsp_conn_->GetNonce(); + cseq = rtsp_conn_->GetCseq() + 1; + + rtsp_conn_ = nullptr; + if(!retry) + { + return -1; + } + retry = false; + } +// } return 0; } @@ -137,4 +153,4 @@ bool RtspPusher::PushFrame(MediaChannelId channelId, AVFrame frame) } return media_session_->HandleFrame(channelId, frame); -} \ No newline at end of file +} From 0546efb304dc0c881e47169ab4b732b8915b96d7 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Tue, 11 May 2021 14:36:20 +0200 Subject: [PATCH 06/21] removed visocon --- example/rtsp_pusher.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/example/rtsp_pusher.cpp b/example/rtsp_pusher.cpp index ce21ea4..e143435 100755 --- a/example/rtsp_pusher.cpp +++ b/example/rtsp_pusher.cpp @@ -57,13 +57,14 @@ int main(int argc, char **argv) // session->AddSource(xop::channel_1, xop::AACSource::CreateNew(44100, 2, false)); rtsp_pusher->AddSession(session); - // To: "5b47756573745d2047656e65726f757320636f617469" ;tag=9dd61ff61e802d8e2bef5f14621ef3c2.cc43 - - std::string serverIP("54.155.36.131"); - uint16_t port = 8554; - std::string channel("live/myStream?playid=1&replaces=609a63c11386cc001241d89a@integrations.visocon.com"); - std::string username("visoconEyesOn"); - std::string password("VdtxeQnwIaZmaQLc"); +/* + std::string serverIP("127.0.0.1"); + uint16_t port = 8009; + std::string channel("ar4-stream"); + std::string username(""); + std::string password(""); +*/ + /* std::string serverIP("192.168.0.32"); uint16_t port = 8554; From 676c3cb4840a49e16cd84836862c48e876ec44db Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Tue, 11 May 2021 15:24:40 +0200 Subject: [PATCH 07/21] update to run pusher from command line --- CMakeLists.txt | 127 +++++++++++++++++++------------- example/rtsp_pusher.cpp | 29 +++++++- src/xop/DigestAuthenticator.cpp | 4 +- 3 files changed, 104 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index de0ca74..3bd8561 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,59 +1,84 @@ -cmake_minimum_required(VERSION 3.5.0) -project(RtspServer) +project(RTSPServer) -include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/net/" "${CMAKE_CURRENT_SOURCE_DIR}/src/xop/") +# Cmake needs some version information +CMAKE_MINIMUM_REQUIRED(VERSION 3.19) -file(GLOB rtspserver_sources - "${CMAKE_CURRENT_SOURCE_DIR}/src/net/*.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/src/net/*.h" - "${CMAKE_CURRENT_SOURCE_DIR}/src/xop/*.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/src/xop/*.h" - ) +set(CMAKE_CXX_STANDARD 14) + +SET(ARCHSTR ${ANDROID_ABI}) +message(STATUS "Architecture: ${ARCHSTR}") + +set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE) +#======================================= +# USER DEFINED VARIABLES + +IF(NOT CMAKE_BUILD_TYPE) + MESSAGE(STATUS "CMAKE_BUILD_TYPE was not specified. Building Debug Version.") + SET(CMAKE_BUILD_TYPE Debug) +ENDIF(NOT CMAKE_BUILD_TYPE) + +#========================================================== + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/src/ + ${CMAKE_CURRENT_SOURCE_DIR}/src/3rdpart +) + +FILE(GLOB NetSources ${CMAKE_CURRENT_SOURCE_DIR}/src/net/*.cpp) +FILE(GLOB NetHeaders ${CMAKE_CURRENT_SOURCE_DIR}/src/net/*.h) +ADD_LIBRARY(net SHARED ${NetSources} ${NetHeaders}) +SET_TARGET_PROPERTIES(net PROPERTIES + DEBUG_POSTFIX d + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/${ARCHSTR}" +) -set(RTSPSERVER_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/Acceptor.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/BufferReader.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/BufferWriter.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/EpollTaskScheduler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/EventLoop.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/Logger.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/MemoryManager.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/NetInterface.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/Pipe.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/SelectTaskScheduler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/SocketUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/Socket.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/TcpConnection.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/TcpServer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/Timer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/Timestamp.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/TaskScheduler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/net/TcpSocket.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/AACSource.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/DigestAuthentication.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/G711ASource.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/H264Source.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/MediaSession.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/H264Parser.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/H265Source.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/RtpConnection.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/RtspConnection.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/RtspMessage.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/RtspPusher.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/RtspServer.cpp +FILE(GLOB XopSources ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/*.cpp) +FILE(GLOB XopHeaders ${CMAKE_CURRENT_SOURCE_DIR}/src/xop/*.h) +ADD_LIBRARY(xop SHARED ${XopSources} ${XopHeaders}) +ADD_DEPENDENCIES(xop net) +TARGET_LINK_LIBRARIES(xop net) +SET_TARGET_PROPERTIES(xop PROPERTIES + DEBUG_POSTFIX d + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/${ARCHSTR}" ) -add_library(RtspServer STATIC ${rtspserver_sources}) -add_library(RtspServer::RtspServer ALIAS RtspServer) +IF(ANDROID) + TARGET_LINK_LIBRARIES(xop log) + TARGET_LINK_LIBRARIES(net log) +ENDIF(ANDROID) -target_include_directories(RtspServer - PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}/src/" - "${CMAKE_CURRENT_SOURCE_DIR}/src/xop/" - "${CMAKE_CURRENT_SOURCE_DIR}/src/3rdpart/" - ) +IF(BUILD_EXECUTABLE) + ADD_EXECUTABLE(rtsp_pusher ${CMAKE_CURRENT_SOURCE_DIR}/example/rtsp_pusher.cpp ) + ADD_DEPENDENCIES(rtsp_pusher net xop) + TARGET_LINK_LIBRARIES(rtsp_pusher net xop) + SET_TARGET_PROPERTIES(rtsp_pusher PROPERTIES + DEBUG_POSTFIX d + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/${ARCHSTR}" + ) -target_link_libraries(RtspServer - PRIVATE - zm-dependency-interface) + ADD_EXECUTABLE(rtsp_h264_file ${CMAKE_CURRENT_SOURCE_DIR}/example/rtsp_h264_file.cpp ) + ADD_DEPENDENCIES(rtsp_h264_file net xop) + TARGET_LINK_LIBRARIES(rtsp_h264_file net xop) + SET_TARGET_PROPERTIES(rtsp_h264_file PROPERTIES + DEBUG_POSTFIX d + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/${ARCHSTR}" + ) + ADD_EXECUTABLE(rtsp_server ${CMAKE_CURRENT_SOURCE_DIR}/example/rtsp_server.cpp ) + ADD_DEPENDENCIES(rtsp_server net xop) + TARGET_LINK_LIBRARIES(rtsp_server net xop) + SET_TARGET_PROPERTIES(rtsp_server PROPERTIES + DEBUG_POSTFIX d + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/${ARCHSTR}" + ) +ENDIF(BUILD_EXECUTABLE) diff --git a/example/rtsp_pusher.cpp b/example/rtsp_pusher.cpp index e143435..e1316e1 100755 --- a/example/rtsp_pusher.cpp +++ b/example/rtsp_pusher.cpp @@ -38,8 +38,8 @@ void sendFrameThread(xop::RtspPusher* rtspPusher, H264File* h264_file); int main(int argc, char **argv) { - if(argc != 2) { - printf("Usage: %s test.h264 \n", argv[0]); + if(argc != 3) { + printf("Usage: %s \n", argv[0]); return 0; } @@ -61,10 +61,33 @@ int main(int argc, char **argv) std::string serverIP("127.0.0.1"); uint16_t port = 8009; std::string channel("ar4-stream"); +*/ std::string username(""); std::string password(""); -*/ + std::string rtspaddr(argv[2]); + size_t it = rtspaddr.find("rtsp://") + strlen("rtsp://"); + std::string tstr = rtspaddr.substr(it,40); // should be within the first 40 chars after rtsp:// + // std::cout << tstr << std::endl; + size_t it2 = tstr.find("@"); + if(it2 != tstr.npos) { + size_t it2 = rtspaddr.find(":",it); + std::cout << "==== user: " << rtspaddr.substr(it, it2-it) << std::endl; + username = rtspaddr.substr(it, it2-it); + size_t it3 = rtspaddr.find("@",it2); + std::cout << "==== pass: " << rtspaddr.substr(it2+1, it3-it2-1) << std::endl; + password = rtspaddr.substr(it2+1, it3-it2-1); + it = it3+1; + } + it2 = rtspaddr.find(":", it); + std::cout << "==== server: " << rtspaddr.substr(it, it2-it) << std::endl; + std::string serverIP = rtspaddr.substr(it, it2-it); + size_t it3 = rtspaddr.find("/",it2+1); + std::cout << "==== port: " << rtspaddr.substr(it2+1, it3-it2-1) << std::endl; + uint16_t port = atoi(rtspaddr.substr(it2+1, it3-it2-1).c_str()); + std::string channel(rtspaddr.substr(it3+1)); + std::cout << "==== channel: " << channel << std::endl; + /* std::string serverIP("192.168.0.32"); uint16_t port = 8554; diff --git a/src/xop/DigestAuthenticator.cpp b/src/xop/DigestAuthenticator.cpp index 36e6b4a..89c6713 100644 --- a/src/xop/DigestAuthenticator.cpp +++ b/src/xop/DigestAuthenticator.cpp @@ -110,7 +110,7 @@ bool DigestAuthenticator::Authenticate( if (nonce.size() > 0 && (GetResponse(nonce, cmd, url) == rtsp_request->GetAuthResponse())) { #if defined(ANDROID) - __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator Authenticate success %s - %s - %s", cmd, url.c_str(), nonce.c_str()); + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator Authenticate success %s - %s - %s", cmd.c_str(), url.c_str(), nonce.c_str()); #else std::cout << "DigestAuthenticator Authenticate success" << cmd << " - " << url.c_str() << " - " << nonce.c_str() << std::endl; #endif @@ -119,7 +119,7 @@ bool DigestAuthenticator::Authenticate( } else { #if defined(ANDROID) - __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator Authenticate failed %s - %s - %s", cmd, url.c_str(), nonce.c_str()); + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator Authenticate failed %s - %s - %s", cmd.c_str(), url.c_str(), nonce.c_str()); #else std::cout << "DigestAuthenticator Authenticate failed" << cmd << " - " << url.c_str() << " - " << nonce.c_str() << std::endl; #endif From c956b3301db21f9fb1f18510bf8649a1c7f33acb Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Tue, 11 May 2021 14:02:44 +0000 Subject: [PATCH 08/21] update linux --- CMakeLists.txt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bd8561..f4939a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ project(RTSPServer) # Cmake needs some version information -CMAKE_MINIMUM_REQUIRED(VERSION 3.19) +CMAKE_MINIMUM_REQUIRED(VERSION 3.16) set(CMAKE_CXX_STANDARD 14) @@ -51,10 +51,14 @@ IF(ANDROID) TARGET_LINK_LIBRARIES(net log) ENDIF(ANDROID) +IF(UNIX AND NOT ANDROID) + SET(LINKLIBS pthread) +ENDIF(UNIX AND NOT ANDROID) + IF(BUILD_EXECUTABLE) ADD_EXECUTABLE(rtsp_pusher ${CMAKE_CURRENT_SOURCE_DIR}/example/rtsp_pusher.cpp ) ADD_DEPENDENCIES(rtsp_pusher net xop) - TARGET_LINK_LIBRARIES(rtsp_pusher net xop) + TARGET_LINK_LIBRARIES(rtsp_pusher net xop ${LINKLIBS}) SET_TARGET_PROPERTIES(rtsp_pusher PROPERTIES DEBUG_POSTFIX d ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" @@ -64,7 +68,7 @@ IF(BUILD_EXECUTABLE) ADD_EXECUTABLE(rtsp_h264_file ${CMAKE_CURRENT_SOURCE_DIR}/example/rtsp_h264_file.cpp ) ADD_DEPENDENCIES(rtsp_h264_file net xop) - TARGET_LINK_LIBRARIES(rtsp_h264_file net xop) + TARGET_LINK_LIBRARIES(rtsp_h264_file net xop ${LINKLIBS}) SET_TARGET_PROPERTIES(rtsp_h264_file PROPERTIES DEBUG_POSTFIX d ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" @@ -74,7 +78,7 @@ IF(BUILD_EXECUTABLE) ADD_EXECUTABLE(rtsp_server ${CMAKE_CURRENT_SOURCE_DIR}/example/rtsp_server.cpp ) ADD_DEPENDENCIES(rtsp_server net xop) - TARGET_LINK_LIBRARIES(rtsp_server net xop) + TARGET_LINK_LIBRARIES(rtsp_server net xop ${LINKLIBS}) SET_TARGET_PROPERTIES(rtsp_server PROPERTIES DEBUG_POSTFIX d ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" From 3362e7234a1e637e0604e46a26fd40985a33cc15 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Wed, 12 May 2021 21:26:12 +0200 Subject: [PATCH 09/21] added RTCP sender info --- src/xop/RtpConnection.cpp | 115 ++++++++++++++++++++++++++++++++++---- src/xop/RtpConnection.h | 7 ++- src/xop/rtp.h | 21 ++++++- 3 files changed, 129 insertions(+), 14 deletions(-) diff --git a/src/xop/RtpConnection.cpp b/src/xop/RtpConnection.cpp index 37d8cc4..761d5ae 100644 --- a/src/xop/RtpConnection.cpp +++ b/src/xop/RtpConnection.cpp @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-9-30 #include "RtpConnection.h" @@ -167,6 +167,82 @@ void RtpConnection::Play() } } +const uint32_t NTP_EPOCH_OFFSET = 2208992400u; +timeval NTP2Timeval(uint32_t msw, uint32_t lsw) +{ + struct timeval t; + t.tv_sec = msw - NTP_EPOCH_OFFSET; + t.tv_usec = (uint32_t)((((double)lsw) * 1000000.0) / ((uint32_t)(~0))); + return t; +} + +void RtpConnection::AssembleRTCPMessage() +{ +// RTP: +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P|X| CC |M| PT | sequence number | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | timestamp | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | synchronization source (SSRC) identifier | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | contributing source (CSRC) identifiers | +// | .... | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + +// RTCP: +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// header |V=2|P| RC | PT=SR=200 | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of sender | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// sender | NTP timestamp, most significant word | +// info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | NTP timestamp, least significant word | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | RTP timestamp | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | sender's packet count | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | sender's octet count | + + RtpPacket rpkt; + rtcp_packet *pkt = reinterpret_cast(rpkt.data.get() + 4); + pkt->header.version = 2; + pkt->header.p = 0; + pkt->header.count = 0; + pkt->header.pt = 200; + pkt->header.length = htons(6); + pkt->ssrc = media_channel_info_[0].rtp_header.ssrc; + // + int32_t* blk = (int32_t*)(rpkt.data.get() + 12); // + 12); + + const std::chrono::time_point now = std::chrono::system_clock::now(); + uint32_t secs = std::chrono::duration_cast(now.time_since_epoch()).count(); + uint64_t nsecs = std::chrono::duration_cast(now.time_since_epoch()).count() - (1e9 * secs); + + auto time_point = chrono::time_point_cast(chrono::steady_clock::now()); + uint32_t rtptm = (int64_t)((time_point.time_since_epoch().count() + 500) / 1000 * 90 ); + + // usecs = (uint32)((((double)lsw) * 1000000.0) / ((uint32)(~0))) + // NTP time stamp is seconds since 1970 as MSW + blk[0] = htonl(secs + NTP_EPOCH_OFFSET); + blk[1] = htonl((uint32_t)((nsecs * 4294967295) / 1000000000)); + blk[2] = htonl(rtptm); // is based on 10 microsecond intervals + blk[3] = htonl(0x00); + blk[4] = htonl(0x00); + + rpkt.last = 1; + rpkt.size = 32; + + SendRtpPacket(xop::channel_0, rpkt, true); +} + void RtpConnection::Record() { for (int chn=0; chntask_scheduler_->AddTriggerEvent([this, channel_id, pkt] { - this->SetFrameType(pkt.type); - this->SetRtpHeader(channel_id, pkt); - if((media_channel_info_[channel_id].is_play || media_channel_info_[channel_id].is_record) && has_key_frame_ ) { + bool ret = rtsp_conn->task_scheduler_->AddTriggerEvent([this, channel_id, pkt, isRtcp] { + if(!isRtcp) + { + this->SetFrameType(pkt.type); + this->SetRtpHeader(channel_id, pkt); + } + if((media_channel_info_[channel_id].is_play || media_channel_info_[channel_id].is_record) && (has_key_frame_ || isRtcp) ) { if(transport_mode_ == RTP_OVER_TCP) { - SendRtpOverTcp(channel_id, pkt); + SendRtpOverTcp(channel_id, pkt, isRtcp); } else { SendRtpOverUdp(channel_id, pkt); @@ -267,7 +348,7 @@ int RtpConnection::SendRtpPacket(MediaChannelId channel_id, RtpPacket pkt) return ret ? 0 : -1; } -int RtpConnection::SendRtpOverTcp(MediaChannelId channel_id, RtpPacket pkt) +int RtpConnection::SendRtpOverTcp(MediaChannelId channel_id, RtpPacket pkt, bool isRtcp) { auto conn = rtsp_connection_.lock(); if (!conn) { @@ -276,10 +357,24 @@ int RtpConnection::SendRtpOverTcp(MediaChannelId channel_id, RtpPacket pkt) uint8_t* rtpPktPtr = pkt.data.get(); rtpPktPtr[0] = '$'; - rtpPktPtr[1] = (char)media_channel_info_[channel_id].rtp_channel; + if(isRtcp) + rtpPktPtr[1] = (char)media_channel_info_[channel_id].rtcp_channel; + else + rtpPktPtr[1] = (char)media_channel_info_[channel_id].rtp_channel; rtpPktPtr[2] = (char)(((pkt.size-4)&0xFF00)>>8); rtpPktPtr[3] = (char)((pkt.size -4)&0xFF); + /* + uint8_t* pk = pkt.data.get(); + //================================ + printf("===================================\n"); + for(int i = 0; i < 32; i+=4) + { + printf("%02x %02x %02x %02x\n", pk[i], pk[i+1], pk[i+2], pk[i+3]); + } + printf("===================================\n"); + */ + conn->Send((char*)rtpPktPtr, pkt.size); return pkt.size; } diff --git a/src/xop/RtpConnection.h b/src/xop/RtpConnection.h index 1eacc89..6c95d27 100644 --- a/src/xop/RtpConnection.h +++ b/src/xop/RtpConnection.h @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-6-8 #ifndef XOP_RTP_CONNECTION_H @@ -69,7 +69,7 @@ class RtpConnection void Teardown(); std::string GetRtpInfo(const std::string& rtsp_url); - int SendRtpPacket(MediaChannelId channel_id, RtpPacket pkt); + int SendRtpPacket(MediaChannelId channel_id, RtpPacket pkt, bool isRtcp = false); bool IsClosed() const { return is_closed_; } @@ -82,9 +82,10 @@ class RtpConnection private: friend class RtspConnection; friend class MediaSession; + void AssembleRTCPMessage(); void SetFrameType(uint8_t frameType = 0); void SetRtpHeader(MediaChannelId channel_id, RtpPacket pkt); - int SendRtpOverTcp(MediaChannelId channel_id, RtpPacket pkt); + int SendRtpOverTcp(MediaChannelId channel_id, RtpPacket pkt, bool isRtcp = false); int SendRtpOverUdp(MediaChannelId channel_id, RtpPacket pkt); std::weak_ptr rtsp_connection_; diff --git a/src/xop/rtp.h b/src/xop/rtp.h index 35ca770..fd26a28 100644 --- a/src/xop/rtp.h +++ b/src/xop/rtp.h @@ -1,4 +1,4 @@ -// PHZ +// PHZ // 2018-6-11 #ifndef XOP_RTP_H @@ -37,6 +37,25 @@ typedef struct _RTP_header unsigned int ssrc; } RtpHeader; + +//=============== TAKEN FROM https://github.com/sipwise/rtpengine +struct rtcp_header { + unsigned count:5; /**< varies by payload type */ + unsigned p:1; /**< padding flag */ + unsigned version:2; /**< packet type */ + unsigned char pt; + uint16_t length; +} __attribute__ ((packed)); + +struct rtcp_packet { + struct rtcp_header header; + uint32_t ssrc; +} __attribute__ ((packed)); + +//=============================== + + + struct MediaChannelInfo { RtpHeader rtp_header; From 3ee6f018e71b71feb9f3f7737ac4554783de0960 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Fri, 14 May 2021 19:51:48 +0200 Subject: [PATCH 10/21] fixed issue with empty header (session id) --- src/xop/RtspMessage.cpp | 25 +++++++++++++++++++++++++ src/xop/RtspMessage.h | 2 ++ 2 files changed, 27 insertions(+) diff --git a/src/xop/RtspMessage.cpp b/src/xop/RtspMessage.cpp index ab63b21..d7f66f7 100644 --- a/src/xop/RtspMessage.cpp +++ b/src/xop/RtspMessage.cpp @@ -598,6 +598,31 @@ size_t RtspRequest::BuildUnauthorizedRes(const char* buf, size_t buf_size, const return strlen(buf); } +string gen_random(const int len) { + + string tmp_s; + static const char alphanum[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + + srand( (unsigned) time(NULL) * getpid()); + + tmp_s.reserve(len); + + for (int i = 0; i < len; ++i) + tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)]; + + + return tmp_s; + +} + +RtspResponse::RtspResponse() +{ + session_ = gen_random(8); +} + bool RtspResponse::ParseResponse(xop::BufferReader *buffer) { if (strstr(buffer->Peek(), "\r\n\r\n") != NULL) { diff --git a/src/xop/RtspMessage.h b/src/xop/RtspMessage.h index 85f1056..a7521a3 100644 --- a/src/xop/RtspMessage.h +++ b/src/xop/RtspMessage.h @@ -130,6 +130,8 @@ class RtspResponse "OPTIONS", "DESCRIBE", "ANNOUNCE", "SETUP", "RECORD", "RTCP", "NONE" }; + + RtspResponse(); bool ParseResponse(xop::BufferReader *buffer); From 000326dc57376607fd3381f6fb21d3762bd2ada9 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Fri, 14 May 2021 20:24:22 +0200 Subject: [PATCH 11/21] fixed server to send file --- example/rtsp_server.cpp | 199 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 188 insertions(+), 11 deletions(-) diff --git a/example/rtsp_server.cpp b/example/rtsp_server.cpp index d055a8c..e0edd4d 100755 --- a/example/rtsp_server.cpp +++ b/example/rtsp_server.cpp @@ -1,4 +1,4 @@ -// RTSP Server +// RTSP Server #include "xop/RtspServer.h" #include "net/Timer.h" @@ -7,17 +7,50 @@ #include #include -void SendFrameThread(xop::RtspServer* rtsp_server, xop::MediaSessionId session_id, int& clients); +class H264File +{ +public: + H264File(int buf_size=500000); + ~H264File(); + + bool Open(const char *path); + void Close(); + + bool IsOpened() const + { return (m_file != NULL); } + + int ReadFrame(char* in_buf, int in_buf_size, bool* end); + +private: + FILE *m_file = NULL; + char *m_buf = NULL; + int m_buf_size = 0; + int m_bytes_used = 0; + int m_count = 0; +}; + +void SendFrameThread(xop::RtspServer* rtsp_server, xop::MediaSessionId session_id, H264File* file, int& clients); int main(int argc, char **argv) -{ +{ + if(argc != 2) { + printf("Usage: %s test.h264 \n", argv[0]); + return 0; + } + int clients = 0; std::string ip = "0.0.0.0"; - std::string rtsp_url = "rtsp://127.0.0.1:554/live"; + std::string rtsp_url = "rtsp://127.0.0.1:8554/live"; + H264File h264_file; + if(!h264_file.Open(argv[1])) { + printf("Open %s failed.\n", argv[1]); + return 0; + } + std::shared_ptr event_loop(new xop::EventLoop()); std::shared_ptr server = xop::RtspServer::Create(event_loop.get()); - if (!server->Start(ip, 554)) { + if (!server->Start(ip, 8554)) { return -1; } @@ -27,15 +60,17 @@ int main(int argc, char **argv) xop::MediaSession *session = xop::MediaSession::CreateNew("live"); // url: rtsp://ip/live session->AddSource(xop::channel_0, xop::H264Source::CreateNew()); - session->AddSource(xop::channel_1, xop::AACSource::CreateNew(44100,2)); + // session->AddSource(xop::channel_1, xop::AACSource::CreateNew(44100,2)); // session->startMulticast(); /* 开启组播(ip,端口随机生成), 默认使用 RTP_OVER_UDP, RTP_OVER_RTSP */ - session->AddNotifyConnectedCallback([] (xop::MediaSessionId sessionId, std::string peer_ip, uint16_t peer_port){ + session->AddNotifyConnectedCallback([&clients] (xop::MediaSessionId sessionId, std::string peer_ip, uint16_t peer_port){ printf("RTSP client connect, ip=%s, port=%hu \n", peer_ip.c_str(), peer_port); + clients++; }); - session->AddNotifyDisconnectedCallback([](xop::MediaSessionId sessionId, std::string peer_ip, uint16_t peer_port) { + session->AddNotifyDisconnectedCallback([&clients](xop::MediaSessionId sessionId, std::string peer_ip, uint16_t peer_port) { printf("RTSP client disconnect, ip=%s, port=%hu \n", peer_ip.c_str(), peer_port); + clients--; }); std::cout << "URL: " << rtsp_url << std::endl; @@ -43,7 +78,7 @@ int main(int argc, char **argv) xop::MediaSessionId session_id = server->AddSession(session); //server->removeMeidaSession(session_id); /* 取消会话, 接口线程安全 */ - std::thread thread(SendFrameThread, server.get(), session_id, std::ref(clients)); + std::thread thread(SendFrameThread, server.get(), session_id, &h264_file, std::ref(clients)); thread.detach(); while(1) { @@ -54,12 +89,34 @@ int main(int argc, char **argv) return 0; } -void SendFrameThread(xop::RtspServer* rtsp_server, xop::MediaSessionId session_id, int& clients) -{ +void SendFrameThread(xop::RtspServer* rtsp_server, xop::MediaSessionId session_id, H264File* h264_file, int& clients) +{ + int buf_size = 2000000; + std::unique_ptr frame_buf(new uint8_t[buf_size]); + while(1) { if(clients > 0) /* 会话有客户端在线, 发送音视频数据 */ { + { + bool end_of_frame = false; + int frame_size = h264_file->ReadFrame((char*)frame_buf.get(), buf_size, &end_of_frame); + if(frame_size > 0) { + xop::AVFrame videoFrame; + videoFrame.type = 0; + videoFrame.timestamp = xop::H264Source::GetTimestamp(); + //videoFrame.buffer.reset(new uint8_t[videoFrame.size]); + //memcpy(videoFrame.buffer.get(), frame_buf.get(), videoFrame.size); + videoFrame.buffer.resize(frame_size); + memcpy(videoFrame.buffer.data(), frame_buf.get(), frame_size); + rtsp_server->PushFrame(session_id, xop::channel_0, videoFrame); + } + else { + break; + } + + xop::Timer::Sleep(40); + } { /* //获取一帧 H264, 打包 @@ -92,3 +149,123 @@ void SendFrameThread(xop::RtspServer* rtsp_server, xop::MediaSessionId session_i xop::Timer::Sleep(1); /* 实际使用需要根据帧率计算延时! */ } } + +H264File::H264File(int buf_size) + : m_buf_size(buf_size) +{ + m_buf = new char[m_buf_size]; +} + +H264File::~H264File() +{ + delete m_buf; +} + +bool H264File::Open(const char *path) +{ + m_file = fopen(path, "rb"); + if(m_file == NULL) { + return false; + } + + return true; +} + +void H264File::Close() +{ + if(m_file) { + fclose(m_file); + m_file = NULL; + m_count = 0; + m_bytes_used = 0; + } +} + +int H264File::ReadFrame(char* in_buf, int in_buf_size, bool* end) +{ + if(m_file == NULL) { + return -1; + } + + int bytes_read = (int)fread(m_buf, 1, m_buf_size, m_file); + if(bytes_read == 0) { + fseek(m_file, 0, SEEK_SET); + m_count = 0; + m_bytes_used = 0; + bytes_read = (int)fread(m_buf, 1, m_buf_size, m_file); + if(bytes_read == 0) { + this->Close(); + return -1; + } + } + + bool is_find_start = false, is_find_end = false; + int i = 0, start_code = 3; + *end = false; + + for (i=0; i0) { + flag = is_find_end = true; + i = bytes_read; + *end = true; + } + + if(!is_find_start || !is_find_end) { + this->Close(); + return -1; + } + + int size = (i<=in_buf_size ? i : in_buf_size); + memcpy(in_buf, m_buf, size); + + if(!flag) { + m_count += 1; + m_bytes_used += i; + } + else { + m_count = 0; + m_bytes_used = 0; + } + + fseek(m_file, m_bytes_used, SEEK_SET); + return size; +} From b51bbef9e1160da38f00cb467a219fa7282aadf7 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Sat, 15 May 2021 00:40:49 +0200 Subject: [PATCH 12/21] added DEBUG to suppress messages --- CMakeLists.txt | 12 ++++-------- src/net/SocketUtil.cpp | 15 ++++++++++++--- src/net/TcpConnection.cpp | 10 ++++++++-- src/net/TcpServer.cpp | 2 ++ src/xop/DigestAuthenticator.cpp | 24 +++++++++++++++--------- src/xop/RtpConnection.cpp | 20 +++++++++++--------- src/xop/RtspConnection.cpp | 22 ++++++++++++++-------- src/xop/RtspMessage.cpp | 14 +++++++------- src/xop/RtspServer.cpp | 2 ++ 9 files changed, 75 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f4939a1..3bd8561 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ project(RTSPServer) # Cmake needs some version information -CMAKE_MINIMUM_REQUIRED(VERSION 3.16) +CMAKE_MINIMUM_REQUIRED(VERSION 3.19) set(CMAKE_CXX_STANDARD 14) @@ -51,14 +51,10 @@ IF(ANDROID) TARGET_LINK_LIBRARIES(net log) ENDIF(ANDROID) -IF(UNIX AND NOT ANDROID) - SET(LINKLIBS pthread) -ENDIF(UNIX AND NOT ANDROID) - IF(BUILD_EXECUTABLE) ADD_EXECUTABLE(rtsp_pusher ${CMAKE_CURRENT_SOURCE_DIR}/example/rtsp_pusher.cpp ) ADD_DEPENDENCIES(rtsp_pusher net xop) - TARGET_LINK_LIBRARIES(rtsp_pusher net xop ${LINKLIBS}) + TARGET_LINK_LIBRARIES(rtsp_pusher net xop) SET_TARGET_PROPERTIES(rtsp_pusher PROPERTIES DEBUG_POSTFIX d ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" @@ -68,7 +64,7 @@ IF(BUILD_EXECUTABLE) ADD_EXECUTABLE(rtsp_h264_file ${CMAKE_CURRENT_SOURCE_DIR}/example/rtsp_h264_file.cpp ) ADD_DEPENDENCIES(rtsp_h264_file net xop) - TARGET_LINK_LIBRARIES(rtsp_h264_file net xop ${LINKLIBS}) + TARGET_LINK_LIBRARIES(rtsp_h264_file net xop) SET_TARGET_PROPERTIES(rtsp_h264_file PROPERTIES DEBUG_POSTFIX d ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" @@ -78,7 +74,7 @@ IF(BUILD_EXECUTABLE) ADD_EXECUTABLE(rtsp_server ${CMAKE_CURRENT_SOURCE_DIR}/example/rtsp_server.cpp ) ADD_DEPENDENCIES(rtsp_server net xop) - TARGET_LINK_LIBRARIES(rtsp_server net xop ${LINKLIBS}) + TARGET_LINK_LIBRARIES(rtsp_server net xop) SET_TARGET_PROPERTIES(rtsp_server PROPERTIES DEBUG_POSTFIX d ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/${ARCHSTR}" diff --git a/src/net/SocketUtil.cpp b/src/net/SocketUtil.cpp index 1cd4bfe..ba0e321 100644 --- a/src/net/SocketUtil.cpp +++ b/src/net/SocketUtil.cpp @@ -100,24 +100,30 @@ void SocketUtil::SetSendBufSize(SOCKET sockfd, int size) void SocketUtil::SetRecvBufSize(SOCKET sockfd, int size) { - if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size)) < 0) + if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size)) < 0) { +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "SocketUtil: Error setting SO_RCVBUF to %d",size); #else std::cerr << "Error setting SO_RCVBUF to " << size << std::endl; #endif +#endif + } } int SocketUtil::GetSendBufSize(SOCKET sockfd) { int optval; socklen_t optlen = sizeof(optval); - if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) + if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) { +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "SocketUtil: Error getting SO_SNDBUF"); #else std::cerr << "Error getting SO_SNDBUF " << std::endl; #endif +#endif + } return optval; } @@ -125,12 +131,15 @@ int SocketUtil::GetRecvBufSize(SOCKET sockfd) { int optval; socklen_t optlen = sizeof(optval); - if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &optval, &optlen) < 0) + if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &optval, &optlen) < 0) { +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "SocketUtil: Error getting SO_RCVBUF"); #else std::cerr << "Error getting SO_RCVBUF " << std::endl; #endif +#endif + } return optval; } diff --git a/src/net/TcpConnection.cpp b/src/net/TcpConnection.cpp index 5d66d2e..dbb720c 100644 --- a/src/net/TcpConnection.cpp +++ b/src/net/TcpConnection.cpp @@ -36,12 +36,15 @@ void TcpConnection::Send(std::shared_ptr data, uint32_t size) { if (!is_closed_) { mutex_.lock(); - if (!write_buffer_->Append(data, size)) + if (!write_buffer_->Append(data, size)) { +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "TcpConnection: write_buffer failed..."); #else std::cerr << "write_buffer failed" << std::endl; #endif +#endif + } mutex_.unlock(); this->HandleWrite(); @@ -52,12 +55,15 @@ void TcpConnection::Send(const char *data, uint32_t size) { if (!is_closed_) { mutex_.lock(); - if ( !write_buffer_->Append(data, size)) + if ( !write_buffer_->Append(data, size)) { +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "TcpConnection: write_buffer failed..."); #else std::cerr << "write_buffer failed" << std::endl; #endif +#endif + } mutex_.unlock(); this->HandleWrite(); diff --git a/src/net/TcpServer.cpp b/src/net/TcpServer.cpp index 128dc9c..23c274f 100644 --- a/src/net/TcpServer.cpp +++ b/src/net/TcpServer.cpp @@ -74,9 +74,11 @@ void TcpServer::Stop() TcpConnection::Ptr TcpServer::OnConnect(SOCKET sockfd) { +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "TcpServer: received connect request..."); #endif +#endif return std::make_shared(event_loop_->GetTaskScheduler().get(), sockfd); } diff --git a/src/xop/DigestAuthenticator.cpp b/src/xop/DigestAuthenticator.cpp index 89c6713..67a1622 100644 --- a/src/xop/DigestAuthenticator.cpp +++ b/src/xop/DigestAuthenticator.cpp @@ -10,11 +10,13 @@ DigestAuthenticator::DigestAuthenticator(std::string realm, std::string username , username_(username) , password_(password) { +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator Constructor"); #else std::cout << "DigestAuthenticator Constructor" << std::endl; #endif +#endif } DigestAuthenticator::~DigestAuthenticator() @@ -24,12 +26,13 @@ DigestAuthenticator::~DigestAuthenticator() std::string DigestAuthenticator::GetNonce() { +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator GetNonce"); #else std::cout << "DigestAuthenticator GetNonce" << std::endl; #endif - +#endif return md5::generate_nonce(); } @@ -40,13 +43,13 @@ std::string DigestAuthenticator::GetResponse(std::string nonce, std::string cmd, auto hex1 = md5::md5_hash_hex(username_ + ":" + realm_ + ":" + password_); auto hex2 = md5::md5_hash_hex(cmd + ":" + url); auto response = md5::md5_hash_hex(hex1 + ":" + nonce + ":" + hex2); - +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator GetResponse"); #else std::cout << "DigestAuthenticator GetResponse" << std::endl; #endif - +#endif return response; } @@ -85,7 +88,7 @@ bool DigestAuthenticator::HandleUnauthorized(BufferReader* buffer, std::string& std::string line(start, firstCrlf); if(line.find("Unauthorized") != line.npos) unauthorized = true; - + if(line.find("WWW-Authenticate") != line.npos && line.find("Digest") != line.npos) { if(parseParam(line, "realm", realm_) && @@ -107,23 +110,24 @@ bool DigestAuthenticator::Authenticate( std::string cmd = rtsp_request->MethodToString[rtsp_request->GetMethod()]; std::string url = rtsp_request->GetRtspUrl(); - if (nonce.size() > 0 && (GetResponse(nonce, cmd, url) == rtsp_request->GetAuthResponse())) { - + if (nonce.size() > 0 && (GetResponse(nonce, cmd, url) == rtsp_request->GetAuthResponse())) + { +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator Authenticate success %s - %s - %s", cmd.c_str(), url.c_str(), nonce.c_str()); #else std::cout << "DigestAuthenticator Authenticate success" << cmd << " - " << url.c_str() << " - " << nonce.c_str() << std::endl; #endif - +#endif return true; } else { - +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator Authenticate failed %s - %s - %s", cmd.c_str(), url.c_str(), nonce.c_str()); #else std::cout << "DigestAuthenticator Authenticate failed" << cmd << " - " << url.c_str() << " - " << nonce.c_str() << std::endl; #endif - +#endif return false; } } @@ -134,10 +138,12 @@ size_t DigestAuthenticator::GetFailedResponse( size_t size) { std::string nonce = md5::generate_nonce(); +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "DigestAuthenticator GetFailedResponse %s - %s - %s", buf.get(), realm_.c_str(), nonce.c_str()); #else std::cout << "DigestAuthenticator GetFailedResponse" << buf.get() << " - " << realm_.c_str() << " - " << nonce.c_str() << std::endl; +#endif #endif return rtsp_request->BuildUnauthorizedRes(buf.get(), size, realm_.c_str(), nonce.c_str()); } diff --git a/src/xop/RtpConnection.cpp b/src/xop/RtpConnection.cpp index 761d5ae..664b72d 100644 --- a/src/xop/RtpConnection.cpp +++ b/src/xop/RtpConnection.cpp @@ -109,10 +109,12 @@ bool RtpConnection::SetupRtpOverUdp(MediaChannelId channel_id, uint16_t rtp_port } SocketUtil::SetSendBufSize(rtpfd_[channel_id], 200*1024); +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "SocketUtil: SendBufSize is %d",SocketUtil::GetSendBufSize(rtpfd_[channel_id])); #else std::cerr << "SendBufSize is " << SocketUtil::GetSendBufSize(rtpfd_[channel_id]) << std::endl; +#endif #endif peer_rtp_addr_[channel_id].sin_family = AF_INET; peer_rtp_addr_[channel_id].sin_addr.s_addr = peer_addr_.sin_addr.s_addr; @@ -192,7 +194,7 @@ void RtpConnection::AssembleRTCPMessage() // | .... | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - + // RTCP: // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -210,7 +212,7 @@ void RtpConnection::AssembleRTCPMessage() // | sender's packet count | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | sender's octet count | - + RtpPacket rpkt; rtcp_packet *pkt = reinterpret_cast(rpkt.data.get() + 4); pkt->header.version = 2; @@ -221,14 +223,14 @@ void RtpConnection::AssembleRTCPMessage() pkt->ssrc = media_channel_info_[0].rtp_header.ssrc; // int32_t* blk = (int32_t*)(rpkt.data.get() + 12); // + 12); - + const std::chrono::time_point now = std::chrono::system_clock::now(); uint32_t secs = std::chrono::duration_cast(now.time_since_epoch()).count(); uint64_t nsecs = std::chrono::duration_cast(now.time_since_epoch()).count() - (1e9 * secs); - + auto time_point = chrono::time_point_cast(chrono::steady_clock::now()); uint32_t rtptm = (int64_t)((time_point.time_since_epoch().count() + 500) / 1000 * 90 ); - + // usecs = (uint32)((((double)lsw) * 1000000.0) / ((uint32)(~0))) // NTP time stamp is seconds since 1970 as MSW blk[0] = htonl(secs + NTP_EPOCH_OFFSET); @@ -236,10 +238,10 @@ void RtpConnection::AssembleRTCPMessage() blk[2] = htonl(rtptm); // is based on 10 microsecond intervals blk[3] = htonl(0x00); blk[4] = htonl(0x00); - + rpkt.last = 1; rpkt.size = 32; - + SendRtpPacket(xop::channel_0, rpkt, true); } @@ -251,7 +253,7 @@ void RtpConnection::Record() media_channel_info_[chn].is_play = true; } } - + AssembleRTCPMessage(); } @@ -374,7 +376,7 @@ int RtpConnection::SendRtpOverTcp(MediaChannelId channel_id, RtpPacket pkt, bool } printf("===================================\n"); */ - + conn->Send((char*)rtpPktPtr, pkt.size); return pkt.size; } diff --git a/src/xop/RtspConnection.cpp b/src/xop/RtspConnection.cpp index 0815793..dd9ad4f 100644 --- a/src/xop/RtspConnection.cpp +++ b/src/xop/RtspConnection.cpp @@ -8,7 +8,7 @@ #include "net/SocketUtil.h" #define USER_AGENT "Lavf57.83.100" //"-_-" -#define RTSP_DEBUG 1 +#define RTSP_DEBUG 0 #define MAX_RTSP_MESSAGE_SIZE 2048 using namespace xop; @@ -22,13 +22,13 @@ RtspConnection::RtspConnection(std::shared_ptr rtsp, TaskScheduler *task_s , rtsp_request_(new RtspRequest) , rtsp_response_(new RtspResponse) { - +#ifdef RTSP_DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspRequest Constructor"); #else std::cout << "RtspConnection Constructor" << std::endl; #endif - +#endif this->SetReadCallback([this](std::shared_ptr conn, xop::BufferReader& buffer) { return this->OnRead(buffer); }); @@ -201,18 +201,20 @@ bool RtspConnection::HandleRtspResponse(BufferReader& buffer) } } else { +#if RTSP_DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::HandleRtspResponse: ParseResponse failed!"); #else cout << "RtspConnection::HandleRtspResponse: ParseResponse failed!" << endl; #endif +#endif //========================================================================= if (conn_mode_ == RTSP_PUSHER) { // check if unauthorized // if yes, try fix it with authenticator // else just return false - + // parse auth info if (authenticator_!=nullptr) { @@ -221,11 +223,13 @@ bool RtspConnection::HandleRtspResponse(BufferReader& buffer) { if(unauthorized) { +#if RTSP_DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::HandleRtspResponse: Resending Options!"); #else cout << "RtspConnection::HandleRtspResponse: Resending Options!" << endl; #endif +#endif rtsp_response_->SetCSeq(rtsp_response_->GetCSeq() + 1); SendOptions(RtspConnection::RTSP_PUSHER); //task_scheduler_->AddTriggerEvent([this]() { @@ -239,12 +243,13 @@ bool RtspConnection::HandleRtspResponse(BufferReader& buffer) return false; //========================================================================= } - +#if RTSP_DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::HandleRtspResponse: ParseResponse ok!"); #else cout << "RtspConnection::HandleRtspResponse: ParseResponse ok!" << endl; #endif +#endif return true; } @@ -470,12 +475,13 @@ void RtspConnection::HandleCmdGetParamter() bool RtspConnection::HandleAuthentication() { +#if RTSP_DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspConnection HandleAuthentication"); #else std::cout << "RtspConnection HandleAuthentication" << std::endl; #endif - +#endif if (authenticator_ != nullptr && !has_auth_) { if (authenticator_->Authenticate(rtsp_request_, _nonce)) { has_auth_ = true; @@ -508,13 +514,13 @@ void RtspConnection::SendOptions(ConnectionMode mode) std::shared_ptr req(new char[2048], std::default_delete()); int size = rtsp_response_->BuildOptionReq(req.get(), 2048, _nonce, authenticator_.get()); - +#if RTSP_DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::SendOptions:"); #else cout << "RtspConnection::SendOptions: " << endl; #endif - +#endif SendRtspMessage(req, size); } diff --git a/src/xop/RtspMessage.cpp b/src/xop/RtspMessage.cpp index d7f66f7..1e58a28 100644 --- a/src/xop/RtspMessage.cpp +++ b/src/xop/RtspMessage.cpp @@ -579,12 +579,13 @@ size_t RtspRequest::BuildUnauthorizedRes(const char *buf, size_t buf_size) size_t RtspRequest::BuildUnauthorizedRes(const char* buf, size_t buf_size, const char* realm, const char* nonce) { +#ifdef DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspRequest BuildUnauthorizedRes"); #else std::cout << "RtspRequest BuildUnauthorizedRes" << std::endl; #endif - +#endif memset((void*)buf, 0, buf_size); snprintf((char*)buf, buf_size, "RTSP/1.0 401 Unauthorized\r\n" @@ -599,23 +600,23 @@ size_t RtspRequest::BuildUnauthorizedRes(const char* buf, size_t buf_size, const } string gen_random(const int len) { - + string tmp_s; static const char alphanum[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; - + srand( (unsigned) time(NULL) * getpid()); tmp_s.reserve(len); for (int i = 0; i < len; ++i) tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)]; - - + + return tmp_s; - + } RtspResponse::RtspResponse() @@ -849,4 +850,3 @@ int RtspResponse::BuildRecordReq(const char* buf, int buf_size, std::string& non method_ = RECORD; return (int)strlen(buf); } - diff --git a/src/xop/RtspServer.cpp b/src/xop/RtspServer.cpp index 64a9a53..6cacea3 100644 --- a/src/xop/RtspServer.cpp +++ b/src/xop/RtspServer.cpp @@ -99,8 +99,10 @@ bool RtspServer::PushFrame(MediaSessionId session_id, MediaChannelId channel_id, TcpConnection::Ptr RtspServer::OnConnect(SOCKET sockfd) { +#if DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspServer: received connect request..."); #endif +#endif return std::make_shared(shared_from_this(), event_loop_->GetTaskScheduler().get(), sockfd); } From 3629e04b70f840a6b507b7c84a981fc9f9de0ac6 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Mon, 17 May 2021 23:00:27 +0200 Subject: [PATCH 13/21] packetization message added --- src/xop/MediaSession.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/xop/MediaSession.cpp b/src/xop/MediaSession.cpp index d715130..a33abbb 100644 --- a/src/xop/MediaSession.cpp +++ b/src/xop/MediaSession.cpp @@ -195,7 +195,9 @@ std::string MediaSession::GetSdpMessage(std::string ip, std::string session_name snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s\r\n", media_sources_[chn]->GetAttribute().c_str()); - + + snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf),"a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6yyAeBr8v/gIgAiIgAAAwACAAADAHgeMGSQ,aOvDyyLA; profile-level-id=64001F\r\n"); + snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), // "a=control:track%d\r\n", chn); "a=control:streamid=%d\r\n", chn); From 5d270146cc6abdf3f9830e314657e015a94aabe9 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Tue, 18 May 2021 20:29:06 +0200 Subject: [PATCH 14/21] update to go into SingleNAL unit mode --- CMakeLists.txt | 2 +- src/xop/H264Source.cpp | 308 +++++++++++++++++++++++++++++++------- src/xop/H264Source.h | 3 + src/xop/MediaSession.cpp | 2 +- src/xop/RtpConnection.cpp | 11 -- 5 files changed, 255 insertions(+), 71 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bd8561..c80b1d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ project(RTSPServer) # Cmake needs some version information -CMAKE_MINIMUM_REQUIRED(VERSION 3.19) +CMAKE_MINIMUM_REQUIRED(VERSION 3.16) set(CMAKE_CXX_STANDARD 14) diff --git a/src/xop/H264Source.cpp b/src/xop/H264Source.cpp index 84775b0..7ad6d1c 100644 --- a/src/xop/H264Source.cpp +++ b/src/xop/H264Source.cpp @@ -23,6 +23,9 @@ H264Source::H264Source(uint32_t framerate) payload_ = 96; media_type_ = H264; clock_rate_ = 90000; + + nalUnitChecked_ = false; + decodeNAL_ = false; } H264Source* H264Source::CreateNew(uint32_t framerate) @@ -47,75 +50,264 @@ string H264Source::GetAttribute() return string("a=rtpmap:96 H264/90000"); } + +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | RTP Header | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |STAP-B NAL HDR | DON | NALU 1 Size | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | NALU 1 Size | NALU 1 HDR | NALU 1 Data | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +// : : +// + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | | NALU 2 Size | NALU 2 HDR | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | NALU 2 Data | +// : : +// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | :...OPTIONAL RTP padding | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +const string naluTypesStrings2[] = +{ + "0: Unspecified (non-VCL)", + "1: Coded slice of a non-IDR picture (VCL)", // P frame + "2: Coded slice data partition A (VCL)", + "3: Coded slice data partition B (VCL)", + "4: Coded slice data partition C (VCL)", + "5: Coded slice of an IDR picture (VCL)", // I frame + "6: Supplemental enhancement information (SEI) (non-VCL)", + "7: Sequence parameter set (non-VCL)", // SPS parameter + "8: Picture parameter set (non-VCL)", // PPS parameter + "9: Access unit delimiter (non-VCL)", + "10: End of sequence (non-VCL)", + "11: End of stream (non-VCL)", + "12: Filler data (non-VCL)", + "13: Sequence parameter set extension (non-VCL)", + "14: Prefix NAL unit (non-VCL)", + "15: Subset sequence parameter set (non-VCL)", + "16: Reserved (non-VCL)", + "17: Reserved (non-VCL)", + "18: Reserved (non-VCL)", + "19: Coded slice of an auxiliary coded picture without partitioning (non-VCL)", + "20: Coded slice extension (non-VCL)", + "21: Coded slice extension for depth view components (non-VCL)", + "22: Reserved (non-VCL)", + "23: Reserved (non-VCL)", + "24: STAP-A Single-time aggregation packet (non-VCL)", + "25: STAP-B Single-time aggregation packet (non-VCL)", + "26: MTAP16 Multi-time aggregation packet (non-VCL)", + "27: MTAP24 Multi-time aggregation packet (non-VCL)", + "28: FU-A Fragmentation unit (non-VCL)", + "29: FU-B Fragmentation unit (non-VCL)", + "30: Unspecified (non-VCL)", + "31: Unspecified (non-VCL)", +}; + bool H264Source::HandleFrame(MediaChannelId channel_id, AVFrame frame) { uint8_t* frame_buf = frame.buffer.data(); uint32_t frame_size = frame.buffer.size(); - - if (frame.timestamp == 0) { - frame.timestamp = GetTimestamp(); + + if(!nalUnitChecked_) + { + if(frame_buf[0] == 0 && frame_buf[1] == 0 && frame_buf[2] == 1) { + decodeNAL_ = true; + } + else if(frame_buf[0] == 0 && frame_buf[1] == 0 && frame_buf[2] == 0 && frame_buf[3] == 1) { + decodeNAL_ = true; + } } - - if (frame_size <= MAX_RTP_PAYLOAD_SIZE) { - RtpPacket rtp_pkt; - rtp_pkt.type = frame.type; - rtp_pkt.timestamp = frame.timestamp; - rtp_pkt.size = frame_size + 4 + RTP_HEADER_SIZE; - rtp_pkt.last = 1; - memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE, frame_buf, frame_size); - - if (send_frame_callback_) { - if (!send_frame_callback_(channel_id, rtp_pkt)) { - return false; + if(decodeNAL_) + { + if (frame.timestamp == 0) { + frame.timestamp = GetTimestamp(); } - } - } else { - char FU_A[2] = {0}; - - FU_A[0] = (frame_buf[0] & 0xE0) | 28; - FU_A[1] = 0x80 | (frame_buf[0] & 0x1f); - - frame_buf += 1; - frame_size -= 1; - - while (frame_size + 2 > MAX_RTP_PAYLOAD_SIZE) { - RtpPacket rtp_pkt; - rtp_pkt.type = frame.type; - rtp_pkt.timestamp = frame.timestamp; - rtp_pkt.size = 4 + RTP_HEADER_SIZE + MAX_RTP_PAYLOAD_SIZE; - rtp_pkt.last = 0; - - rtp_pkt.data.get()[RTP_HEADER_SIZE+4] = FU_A[0]; - rtp_pkt.data.get()[RTP_HEADER_SIZE+5] = FU_A[1]; - memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE+2, frame_buf, MAX_RTP_PAYLOAD_SIZE-2); - - if (send_frame_callback_) { - if (!send_frame_callback_(channel_id, rtp_pkt)) - return false; + + // we received the raw byte stream - we need to packetize it into individual single NALU units (essentially + // just have RTP header + data of NAL + // parse full buffer + int nalutypes[32]; + int nalustart[32]; + int naluend[32]; + int cnt = 0; + for (int i = 0; i < frame_size-1; i++) { + if (i >= 3) { + if(frame_buf[i] == 0x01 && frame_buf[i-1] == 0x00 && frame_buf[i-2] == 0x00) + { + int nalu_type = ((uint8_t)frame_buf[i+1] & 0x1F); +#if DEBUG +#if ANDROID + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME,"=== FOUND NAL UNIT \"%@\" FOUND at %i", naluTypesStrings2[nalu_type], i); +#else + printf("=== FOUND NAL UNIT \"%@\" FOUND at %i", naluTypesStrings2[nalu_type], i); +#endif +#endif + nalutypes[cnt] = nalu_type; + nalustart[cnt] = i+1; // first element + if(cnt > 0) + naluend[cnt-1] = i-4; // last element that counts! + cnt++; + } + else if (frame_buf[i] == 0x01 && frame_buf[i-1] == 0x00 && frame_buf[i-2] == 0x00 && frame_buf[i-3] == 0x00) + { + int nalu_type = ((uint8_t)frame_buf[i+1] & 0x1F); +#if DEBUG +#if ANDROID + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME,"=== FOUND NAL UNIT \"%@\" FOUND at %i", naluTypesStrings2[nalu_type], i); +#else + printf("=== FOUND NAL UNIT \"%@\" FOUND at %i", naluTypesStrings2[nalu_type], i); +#endif +#endif + nalutypes[cnt] = nalu_type; + nalustart[cnt] = i+1; // first element + if(cnt > 0) + naluend[cnt-1] = i-4; // last element that counts! + cnt++; + } } + } + naluend[cnt-1] = frame_size-1; + + // now we have the individual NAL units - lets send them individually... + for(int i = 0; i < cnt; i++) + { + int this_size = naluend[i] - nalustart[i] + 1; + uint8_t* this_buf = frame_buf + nalustart[i]; + + if (this_size <= MAX_RTP_PAYLOAD_SIZE) { + RtpPacket rtp_pkt; + rtp_pkt.type = frame.type; + rtp_pkt.timestamp = frame.timestamp; + rtp_pkt.size = this_size + 4 + RTP_HEADER_SIZE; + rtp_pkt.last = 1; + memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE, this_buf, this_size); + + if (send_frame_callback_) { + if (!send_frame_callback_(channel_id, rtp_pkt)) { + return false; + } + } + } else { + char FU_A[2] = {0}; + + FU_A[0] = (this_buf[0] & 0xE0) | 28; + FU_A[1] = 0x80 | (this_buf[0] & 0x1f); + + this_buf += 1; + this_size -= 1; + + while (this_size + 2 > MAX_RTP_PAYLOAD_SIZE) { + RtpPacket rtp_pkt; + rtp_pkt.type = frame.type; + rtp_pkt.timestamp = frame.timestamp; + rtp_pkt.size = 4 + RTP_HEADER_SIZE + MAX_RTP_PAYLOAD_SIZE; + rtp_pkt.last = 0; + + rtp_pkt.data.get()[RTP_HEADER_SIZE+4] = FU_A[0]; + rtp_pkt.data.get()[RTP_HEADER_SIZE+5] = FU_A[1]; + memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE+2, this_buf, MAX_RTP_PAYLOAD_SIZE-2); + + if (send_frame_callback_) { + if (!send_frame_callback_(channel_id, rtp_pkt)) + return false; + } + + this_buf += MAX_RTP_PAYLOAD_SIZE - 2; + this_size -= MAX_RTP_PAYLOAD_SIZE - 2; - frame_buf += MAX_RTP_PAYLOAD_SIZE - 2; - frame_size -= MAX_RTP_PAYLOAD_SIZE - 2; + FU_A[1] &= ~0x80; + } - FU_A[1] &= ~0x80; + { + RtpPacket rtp_pkt; + rtp_pkt.type = frame.type; + rtp_pkt.timestamp = frame.timestamp; + rtp_pkt.size = 4 + RTP_HEADER_SIZE + 2 + this_size; + rtp_pkt.last = 1; + + FU_A[1] |= 0x40; + rtp_pkt.data.get()[RTP_HEADER_SIZE+4] = FU_A[0]; + rtp_pkt.data.get()[RTP_HEADER_SIZE+5] = FU_A[1]; + memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE+2, this_buf, this_size); + + if (send_frame_callback_) { + if (!send_frame_callback_(channel_id, rtp_pkt)) { + return false; + } + } + } + } + } + } + else // WE RECEIVED THE BUFS ALREADY - JUST SEND NALUS AS BEFORE + { + if (frame.timestamp == 0) { + frame.timestamp = GetTimestamp(); } - { - RtpPacket rtp_pkt; - rtp_pkt.type = frame.type; - rtp_pkt.timestamp = frame.timestamp; - rtp_pkt.size = 4 + RTP_HEADER_SIZE + 2 + frame_size; - rtp_pkt.last = 1; - - FU_A[1] |= 0x40; - rtp_pkt.data.get()[RTP_HEADER_SIZE+4] = FU_A[0]; - rtp_pkt.data.get()[RTP_HEADER_SIZE+5] = FU_A[1]; - memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE+2, frame_buf, frame_size); - - if (send_frame_callback_) { - if (!send_frame_callback_(channel_id, rtp_pkt)) { - return false; - } + if (frame_size <= MAX_RTP_PAYLOAD_SIZE) { + RtpPacket rtp_pkt; + rtp_pkt.type = frame.type; + rtp_pkt.timestamp = frame.timestamp; + rtp_pkt.size = frame_size + 4 + RTP_HEADER_SIZE; + rtp_pkt.last = 1; + memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE, frame_buf, frame_size); + + if (send_frame_callback_) { + if (!send_frame_callback_(channel_id, rtp_pkt)) { + return false; + } + } + } else { + char FU_A[2] = {0}; + + FU_A[0] = (frame_buf[0] & 0xE0) | 28; + FU_A[1] = 0x80 | (frame_buf[0] & 0x1f); + + frame_buf += 1; + frame_size -= 1; + + while (frame_size + 2 > MAX_RTP_PAYLOAD_SIZE) { + RtpPacket rtp_pkt; + rtp_pkt.type = frame.type; + rtp_pkt.timestamp = frame.timestamp; + rtp_pkt.size = 4 + RTP_HEADER_SIZE + MAX_RTP_PAYLOAD_SIZE; + rtp_pkt.last = 0; + + rtp_pkt.data.get()[RTP_HEADER_SIZE+4] = FU_A[0]; + rtp_pkt.data.get()[RTP_HEADER_SIZE+5] = FU_A[1]; + memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE+2, frame_buf, MAX_RTP_PAYLOAD_SIZE-2); + + if (send_frame_callback_) { + if (!send_frame_callback_(channel_id, rtp_pkt)) + return false; + } + + frame_buf += MAX_RTP_PAYLOAD_SIZE - 2; + frame_size -= MAX_RTP_PAYLOAD_SIZE - 2; + + FU_A[1] &= ~0x80; + } + + { + RtpPacket rtp_pkt; + rtp_pkt.type = frame.type; + rtp_pkt.timestamp = frame.timestamp; + rtp_pkt.size = 4 + RTP_HEADER_SIZE + 2 + frame_size; + rtp_pkt.last = 1; + + FU_A[1] |= 0x40; + rtp_pkt.data.get()[RTP_HEADER_SIZE+4] = FU_A[0]; + rtp_pkt.data.get()[RTP_HEADER_SIZE+5] = FU_A[1]; + memcpy(rtp_pkt.data.get()+4+RTP_HEADER_SIZE+2, frame_buf, frame_size); + + if (send_frame_callback_) { + if (!send_frame_callback_(channel_id, rtp_pkt)) { + return false; + } + } } } } diff --git a/src/xop/H264Source.h b/src/xop/H264Source.h index 576095b..2622159 100644 --- a/src/xop/H264Source.h +++ b/src/xop/H264Source.h @@ -33,6 +33,9 @@ class H264Source : public MediaSource private: H264Source(uint32_t framerate); + bool nalUnitChecked_; + bool decodeNAL_; + uint32_t framerate_ = 25; }; diff --git a/src/xop/MediaSession.cpp b/src/xop/MediaSession.cpp index a33abbb..95d36d8 100644 --- a/src/xop/MediaSession.cpp +++ b/src/xop/MediaSession.cpp @@ -196,7 +196,7 @@ std::string MediaSession::GetSdpMessage(std::string ip, std::string session_name "%s\r\n", media_sources_[chn]->GetAttribute().c_str()); - snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf),"a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6yyAeBr8v/gIgAiIgAAAwACAAADAHgeMGSQ,aOvDyyLA; profile-level-id=64001F\r\n"); + //snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf),"a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6yyAeBr8v/gIgAiIgAAAwACAAADAHgeMGSQ,aOvDyyLA; profile-level-id=64001F\r\n"); snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), // "a=control:track%d\r\n", chn); diff --git a/src/xop/RtpConnection.cpp b/src/xop/RtpConnection.cpp index 664b72d..c2562c6 100644 --- a/src/xop/RtpConnection.cpp +++ b/src/xop/RtpConnection.cpp @@ -366,17 +366,6 @@ int RtpConnection::SendRtpOverTcp(MediaChannelId channel_id, RtpPacket pkt, bool rtpPktPtr[2] = (char)(((pkt.size-4)&0xFF00)>>8); rtpPktPtr[3] = (char)((pkt.size -4)&0xFF); - /* - uint8_t* pk = pkt.data.get(); - //================================ - printf("===================================\n"); - for(int i = 0; i < 32; i+=4) - { - printf("%02x %02x %02x %02x\n", pk[i], pk[i+1], pk[i+2], pk[i+3]); - } - printf("===================================\n"); - */ - conn->Send((char*)rtpPktPtr, pkt.size); return pkt.size; } From 90e5573f59935858a89de0d2cf5d3ed8fb0f4192 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Wed, 19 May 2021 20:46:00 +0200 Subject: [PATCH 15/21] teardown implemented --- src/xop/H264Source.cpp | 2 +- src/xop/RtspConnection.cpp | 34 ++++++++++- src/xop/RtspConnection.h | 1 + src/xop/RtspMessage.cpp | 119 ++++++++++++++++++++++++++++++------- src/xop/RtspMessage.h | 12 ++-- src/xop/RtspPusher.cpp | 25 ++++++++ 6 files changed, 164 insertions(+), 29 deletions(-) diff --git a/src/xop/H264Source.cpp b/src/xop/H264Source.cpp index 7ad6d1c..052f170 100644 --- a/src/xop/H264Source.cpp +++ b/src/xop/H264Source.cpp @@ -147,7 +147,7 @@ bool H264Source::HandleFrame(MediaChannelId channel_id, AVFrame frame) nalutypes[cnt] = nalu_type; nalustart[cnt] = i+1; // first element if(cnt > 0) - naluend[cnt-1] = i-4; // last element that counts! + naluend[cnt-1] = i-3; // last element that counts! cnt++; } else if (frame_buf[i] == 0x01 && frame_buf[i-1] == 0x00 && frame_buf[i-2] == 0x00 && frame_buf[i-3] == 0x00) diff --git a/src/xop/RtspConnection.cpp b/src/xop/RtspConnection.cpp index dd9ad4f..8df89b4 100644 --- a/src/xop/RtspConnection.cpp +++ b/src/xop/RtspConnection.cpp @@ -7,7 +7,7 @@ #include "MediaSource.h" #include "net/SocketUtil.h" -#define USER_AGENT "Lavf57.83.100" //"-_-" +#define USER_AGENT "ar4rtsp" //Lavf57.83.100" //"-_-" #define RTSP_DEBUG 0 #define MAX_RTSP_MESSAGE_SIZE 2048 @@ -177,7 +177,8 @@ bool RtspConnection::HandleRtspResponse(BufferReader& buffer) #endif } #endif - if (rtsp_response_->ParseResponse(&buffer)) { + + if (rtsp_response_->ParseResponse(&buffer)) { RtspResponse::Method method = rtsp_response_->GetMethod(); switch (method) { @@ -524,6 +525,35 @@ void RtspConnection::SendOptions(ConnectionMode mode) SendRtspMessage(req, size); } +void RtspConnection::SendTeardown(ConnectionMode mode) +{ + if (rtp_conn_ == nullptr) { + rtp_conn_.reset(new RtpConnection(shared_from_this())); + } + + auto rtsp = rtsp_.lock(); + if (!rtsp) { + HandleClose(); + return; + } + + conn_mode_ = mode; + rtsp_response_->SetUserAgent(USER_AGENT); + rtsp_response_->SetRtspUrl(rtsp->GetRtspUrl().c_str()); + + std::shared_ptr req(new char[2048], std::default_delete()); + int size = rtsp_response_->BuildTeardownReq(req.get(), 2048, _nonce, authenticator_.get()); +#if RTSP_DEBUG + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspConnection::SendTeardown:"); + #else + cout << "RtspConnection::SendTeardown: " << endl; + #endif +#endif + SendRtspMessage(req, size); + rtp_conn_->Teardown(); +} + void RtspConnection::SendAnnounce() { MediaSession::Ptr media_session = nullptr; diff --git a/src/xop/RtspConnection.h b/src/xop/RtspConnection.h index cc5f7dc..88323d4 100644 --- a/src/xop/RtspConnection.h +++ b/src/xop/RtspConnection.h @@ -119,6 +119,7 @@ class RtspConnection : public TcpConnection bool HandleAuthentication(); void SendOptions(ConnectionMode mode= RTSP_SERVER); + void SendTeardown(ConnectionMode mode= RTSP_SERVER); void SendDescribe(); void SendAnnounce(); void SendSetup(); diff --git a/src/xop/RtspMessage.cpp b/src/xop/RtspMessage.cpp index 1e58a28..991cf2c 100644 --- a/src/xop/RtspMessage.cpp +++ b/src/xop/RtspMessage.cpp @@ -412,6 +412,24 @@ int RtspRequest::BuildOptionRes(const char* buf, int buf_size) return (int)strlen(buf); } +/* +int RtspRequest::BuildTeardownMSG(const char* buf, int buf_size, uint32_t session_id) +{ + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "TEARDOWN rtsp://127.0.0.1:8554/live RTSP/1.0\r\n" + "CSeq: %u\r\n" + "Session: %llu\r\n" + "\r\n", + this->GetCSeq(), + session_id); + + method_ = TEARDOWN; + + return (int)strlen(buf); +} +*/ + int RtspRequest::BuildDescribeRes(const char* buf, int buf_size, const char* sdp) { memset((void*)buf, 0, buf_size); @@ -436,7 +454,7 @@ int RtspRequest::BuildSetupMulticastRes(const char* buf, int buf_size, const cha "RTSP/1.0 200 OK\r\n" "CSeq: %u\r\n" "Transport: RTP/AVP;multicast;destination=%s;source=%s;port=%u-0;ttl=255\r\n" - "Session: %u\r\n" + "Session: %llu\r\n" "\r\n", this->GetCSeq(), multicast_ip, @@ -454,7 +472,7 @@ int RtspRequest::BuildSetupUdpRes(const char* buf, int buf_size, uint16_t rtp_ch "RTSP/1.0 200 OK\r\n" "CSeq: %u\r\n" "Transport: RTP/AVP;unicast;client_port=%hu-%hu;server_port=%hu-%hu\r\n" - "Session: %u\r\n" + "Session: %llu\r\n" "\r\n", this->GetCSeq(), this->GetRtpPort(), @@ -473,7 +491,7 @@ int RtspRequest::BuildSetupTcpRes(const char* buf, int buf_size, uint16_t rtp_ch "RTSP/1.0 200 OK\r\n" "CSeq: %u\r\n" "Transport: RTP/AVP/TCP;unicast;interleaved=%d-%d\r\n" - "Session: %u\r\n" + "Session: %llu\r\n" "\r\n", this->GetCSeq(), rtp_chn, rtcp_chn, @@ -507,7 +525,7 @@ int RtspRequest::BuildTeardownRes(const char* buf, int buf_size, uint32_t sessio snprintf((char*)buf, buf_size, "RTSP/1.0 200 OK\r\n" "CSeq: %d\r\n" - "Session: %u\r\n" + "Session: %llu\r\n" "\r\n", this->GetCSeq(), session_id); @@ -521,7 +539,7 @@ int RtspRequest::BuildGetParamterRes(const char* buf, int buf_size, uint32_t ses snprintf((char*)buf, buf_size, "RTSP/1.0 200 OK\r\n" "CSeq: %d\r\n" - "Session: %u\r\n" + "Session: %llu\r\n" "\r\n", this->GetCSeq(), session_id); @@ -599,7 +617,25 @@ size_t RtspRequest::BuildUnauthorizedRes(const char* buf, size_t buf_size, const return strlen(buf); } -string gen_random(const int len) { +uint32_t gen_random(const int len) { + + string tmp_s; + static const char num[] = + "0123456789"; + + srand( (unsigned) time(NULL) * getpid()); + + tmp_s.reserve(len); + + for (int i = 0; i < len; ++i) + tmp_s += num[rand() % (sizeof(num) - 1)]; + + + return std::stoi(tmp_s); + +} + +string gen_randomString(const int len) { string tmp_s; static const char alphanum[] = @@ -635,7 +671,7 @@ bool RtspResponse::ParseResponse(xop::BufferReader *buffer) if (ptr != NULL) { char session_id[50] = {0}; if (sscanf(ptr, "%*[^:]: %s", session_id) == 1) - session_ = session_id; + session_ = std::stol(session_id); } cseq_++; @@ -678,6 +714,43 @@ int RtspResponse::BuildOptionReq(const char* buf, int buf_size, std::string& non return (int)strlen(buf); } +int RtspResponse::BuildTeardownReq(const char* buf, int buf_size, std::string& nonce, Authenticator* auth) +{ + if(auth != nullptr && nonce.size() > 0) + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "TEARDOWN %s RTSP/1.0\r\n" + "CSeq: %u\r\n" + "User-Agent: %s\r\n" + "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n" + "Session: %llu\r\n" + "\r\n", + rtsp_url_.c_str(), + this->GetCSeq() + 1, + user_agent_.c_str(), + auth->GetUsername().c_str(), auth->GetRealm().c_str(), nonce.c_str(), rtsp_url_.c_str(), + auth->GetResponse(nonce, "TEARDOWN", rtsp_url_.c_str()).c_str(), + this->GetSession()); + } + else + { + memset((void*)buf, 0, buf_size); + snprintf((char*)buf, buf_size, + "TEARDOWN %s RTSP/1.0\r\n" + "CSeq: %u\r\n" + "User-Agent: %s\r\n" + "Session: %llu\r\n" + "\r\n", + rtsp_url_.c_str(), + this->GetCSeq() + 1, + user_agent_.c_str(), + this->GetSession()); + } + method_ = TEARDOWN; + return (int)strlen(buf); +} + int RtspResponse::BuildAnnounceReq(const char* buf, int buf_size, const char *sdp, std::string& nonce, Authenticator* auth) { if(auth != nullptr && nonce.size() > 0) @@ -689,7 +762,7 @@ int RtspResponse::BuildAnnounceReq(const char* buf, int buf_size, const char *sd "CSeq: %u\r\n" "User-Agent: %s\r\n" "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n" - "Session: %s\r\n" + "Session: %llu\r\n" "Content-Length: %d\r\n" "\r\n" "%s", @@ -698,7 +771,7 @@ int RtspResponse::BuildAnnounceReq(const char* buf, int buf_size, const char *sd user_agent_.c_str(), auth->GetUsername().c_str(), auth->GetRealm().c_str(), nonce.c_str(), rtsp_url_.c_str(), auth->GetResponse(nonce, "ANNOUNCE", rtsp_url_.c_str()).c_str(), - this->GetSession().c_str(), + this->GetSession(), (int)strlen(sdp), sdp); } @@ -710,14 +783,14 @@ int RtspResponse::BuildAnnounceReq(const char* buf, int buf_size, const char *sd "Content-Type: application/sdp\r\n" "CSeq: %u\r\n" "User-Agent: %s\r\n" - "Session: %s\r\n" + "Session: %llu\r\n" "Content-Length: %d\r\n" "\r\n" "%s", rtsp_url_.c_str(), this->GetCSeq() + 1, user_agent_.c_str(), - this->GetSession().c_str(), + this->GetSession(), (int)strlen(sdp), sdp); } @@ -736,12 +809,14 @@ int RtspResponse::BuildDescribeReq(const char* buf, int buf_size, std::string& n "Accept: application/sdp\r\n" "User-Agent: %s\r\n" "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n" + "Session: %llu\r\n" "\r\n", rtsp_url_.c_str(), this->GetCSeq() + 1, user_agent_.c_str(), auth->GetUsername().c_str(), auth->GetRealm().c_str(), nonce.c_str(), rtsp_url_.c_str(), - auth->GetResponse(nonce, "DESCRIBE", rtsp_url_.c_str()).c_str()); + auth->GetResponse(nonce, "DESCRIBE", rtsp_url_.c_str()).c_str(), + this->GetSession()); } else { @@ -751,10 +826,12 @@ int RtspResponse::BuildDescribeReq(const char* buf, int buf_size, std::string& n "CSeq: %u\r\n" "Accept: application/sdp\r\n" "User-Agent: %s\r\n" + "Session: %llu\r\n" "\r\n", rtsp_url_.c_str(), this->GetCSeq() + 1, - user_agent_.c_str()); + user_agent_.c_str(), + this->GetSession()); } method_ = DESCRIBE; return (int)strlen(buf); @@ -776,7 +853,7 @@ int RtspResponse::BuildSetupTcpReq(const char* buf, int buf_size, int trackId, s "Transport: RTP/AVP/TCP;unicast;mode=record;interleaved=%d-%d\r\n" "CSeq: %u\r\n" "User-Agent: %s\r\n" - "Session: %s\r\n" + "Session: %llu\r\n" "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s/streamid=%d\", response=\"%s\"\r\n" "\r\n", rtsp_url_.c_str(), @@ -785,7 +862,7 @@ int RtspResponse::BuildSetupTcpReq(const char* buf, int buf_size, int trackId, s interleaved[1], this->GetCSeq() + 1, user_agent_.c_str(), - this->GetSession().c_str(), + this->GetSession(), auth->GetUsername().c_str(), auth->GetRealm().c_str(), nonce.c_str(), rtsp_url_.c_str(), trackId, auth->GetResponse(nonce, "SETUP", (rtsp_url_ + "/streamid=" + std::to_string(trackId)).c_str()).c_str()); } @@ -798,7 +875,7 @@ int RtspResponse::BuildSetupTcpReq(const char* buf, int buf_size, int trackId, s "Transport: RTP/AVP/TCP;unicast;mode=record;interleaved=%d-%d\r\n" "CSeq: %u\r\n" "User-Agent: %s\r\n" - "Session: %s\r\n" + "Session: %llu\r\n" "\r\n", rtsp_url_.c_str(), trackId, @@ -806,7 +883,7 @@ int RtspResponse::BuildSetupTcpReq(const char* buf, int buf_size, int trackId, s interleaved[1], this->GetCSeq() + 1, user_agent_.c_str(), - this->GetSession().c_str()); + this->GetSession()); } method_ = SETUP; return (int)strlen(buf); @@ -822,13 +899,13 @@ int RtspResponse::BuildRecordReq(const char* buf, int buf_size, std::string& non "Range: npt=0.000-\r\n" "CSeq: %u\r\n" "User-Agent: %s\r\n" - "Session: %s\r\n" + "Session: %llu\r\n" "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n" "\r\n", rtsp_url_.c_str(), this->GetCSeq() + 1, user_agent_.c_str(), - this->GetSession().c_str(), + this->GetSession(), auth->GetUsername().c_str(), auth->GetRealm().c_str(), nonce.c_str(), rtsp_url_.c_str(), auth->GetResponse(nonce, "RECORD", rtsp_url_.c_str()).c_str()); } @@ -840,12 +917,12 @@ int RtspResponse::BuildRecordReq(const char* buf, int buf_size, std::string& non "Range: npt=0.000-\r\n" "CSeq: %u\r\n" "User-Agent: %s\r\n" - "Session: %s\r\n" + "Session: %llu\r\n" "\r\n", rtsp_url_.c_str(), this->GetCSeq() + 1, user_agent_.c_str(), - this->GetSession().c_str()); + this->GetSession()); } method_ = RECORD; return (int)strlen(buf); diff --git a/src/xop/RtspMessage.h b/src/xop/RtspMessage.h index a7521a3..3bdf5c9 100644 --- a/src/xop/RtspMessage.h +++ b/src/xop/RtspMessage.h @@ -89,6 +89,7 @@ class RtspRequest int BuildSetupUdpRes(const char* buf, int buf_size, uint16_t rtp_chn, uint16_t rtcp_chn, uint32_t session_id); int BuildPlayRes(const char* buf, int buf_size, const char* rtp_info, uint32_t session_id); int BuildTeardownRes(const char* buf, int buf_size, uint32_t session_id); + //int BuildTeardownMSG(const char* buf, int buf_size, uint32_t session_id); int BuildGetParamterRes(const char* buf, int buf_size, uint32_t session_id); int BuildNotFoundRes(const char* buf, int buf_size); int BuildServerErrorRes(const char* buf, int buf_size); @@ -121,14 +122,14 @@ class RtspResponse public: enum Method { - OPTIONS=0, DESCRIBE, ANNOUNCE, SETUP, RECORD, RTCP, + OPTIONS=0, DESCRIBE, ANNOUNCE, SETUP, RECORD, RTCP, TEARDOWN, NONE, }; - const char* MethodToString[7] = + const char* MethodToString[8] = { "OPTIONS", "DESCRIBE", "ANNOUNCE", "SETUP", "RECORD", "RTCP", - "NONE" + "TEARDOWN", "NONE" }; RtspResponse(); @@ -145,7 +146,7 @@ class RtspResponse { return cseq_; } void SetCSeq(uint32_t cseq) { cseq_ = cseq; } - std::string GetSession() const + uint64_t GetSession() const { return session_; } void SetUserAgent(const char *user_agent) @@ -158,6 +159,7 @@ class RtspResponse int BuildDescribeReq(const char* buf, int buf_size, std::string& nonce, Authenticator* auth); int BuildAnnounceReq(const char* buf, int buf_size, const char *sdp, std::string& nonce, Authenticator* auth); int BuildSetupTcpReq(const char* buf, int buf_size, int channel, std::string& nonce, Authenticator* auth); + int BuildTeardownReq(const char* buf, int buf_size, std::string& nonce, Authenticator* auth); int BuildRecordReq(const char* buf, int buf_size, std::string& nonce, Authenticator* auth); private: @@ -165,7 +167,7 @@ class RtspResponse uint32_t cseq_ = 0; std::string user_agent_; std::string rtsp_url_; - std::string session_; + uint64_t session_; }; } diff --git a/src/xop/RtspPusher.cpp b/src/xop/RtspPusher.cpp index e61c00b..c88945a 100644 --- a/src/xop/RtspPusher.cpp +++ b/src/xop/RtspPusher.cpp @@ -126,6 +126,31 @@ void RtspPusher::Close() std::lock_guard lock(mutex_); if (rtsp_conn_ != nullptr) { + + // send tear-down + //TEARDOWN + task_scheduler_ = event_loop_->GetTaskScheduler().get(); + event_loop_->AddTriggerEvent([this]() { + rtsp_conn_->SendTeardown(RtspConnection::RTSP_PUSHER); + }); + + static xop::Timestamp timestamp; + int timeout = 2000; + if (timeout <= 0) { + timeout = 5000; + } + + timeout -= (int)timestamp.Elapsed(); + if (timeout < 0) { + timeout = 1000; + } + // we should check authentication status here! + do + { + xop::Timer::Sleep(100); + timeout -= 100; + } while (rtsp_conn_->IsRecord() && timeout > 0); + std::shared_ptr rtsp_conn = rtsp_conn_; SOCKET sockfd = rtsp_conn->GetSocket(); task_scheduler_->AddTriggerEvent([sockfd, rtsp_conn]() { From 68a5c1efca90f959d731423dafb06b3fa922e61d Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Wed, 19 May 2021 21:04:41 +0200 Subject: [PATCH 16/21] fixed warning --- src/xop/RtspMessage.cpp | 14 +++++++------- src/xop/RtspMessage.h | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/xop/RtspMessage.cpp b/src/xop/RtspMessage.cpp index 991cf2c..3c28a39 100644 --- a/src/xop/RtspMessage.cpp +++ b/src/xop/RtspMessage.cpp @@ -447,7 +447,7 @@ int RtspRequest::BuildDescribeRes(const char* buf, int buf_size, const char* sdp return (int)strlen(buf); } -int RtspRequest::BuildSetupMulticastRes(const char* buf, int buf_size, const char* multicast_ip, uint16_t port, uint32_t session_id) +int RtspRequest::BuildSetupMulticastRes(const char* buf, int buf_size, const char* multicast_ip, uint16_t port, uint64_t session_id) { memset((void*)buf, 0, buf_size); snprintf((char*)buf, buf_size, @@ -465,7 +465,7 @@ int RtspRequest::BuildSetupMulticastRes(const char* buf, int buf_size, const cha return (int)strlen(buf); } -int RtspRequest::BuildSetupUdpRes(const char* buf, int buf_size, uint16_t rtp_chn, uint16_t rtcp_chn, uint32_t session_id) +int RtspRequest::BuildSetupUdpRes(const char* buf, int buf_size, uint16_t rtp_chn, uint16_t rtcp_chn, uint64_t session_id) { memset((void*)buf, 0, buf_size); snprintf((char*)buf, buf_size, @@ -484,7 +484,7 @@ int RtspRequest::BuildSetupUdpRes(const char* buf, int buf_size, uint16_t rtp_ch return (int)strlen(buf); } -int RtspRequest::BuildSetupTcpRes(const char* buf, int buf_size, uint16_t rtp_chn, uint16_t rtcp_chn, uint32_t session_id) +int RtspRequest::BuildSetupTcpRes(const char* buf, int buf_size, uint16_t rtp_chn, uint16_t rtcp_chn, uint64_t session_id) { memset((void*)buf, 0, buf_size); snprintf((char*)buf, buf_size, @@ -500,14 +500,14 @@ int RtspRequest::BuildSetupTcpRes(const char* buf, int buf_size, uint16_t rtp_ch return (int)strlen(buf); } -int RtspRequest::BuildPlayRes(const char* buf, int buf_size, const char* rtpInfo, uint32_t session_id) +int RtspRequest::BuildPlayRes(const char* buf, int buf_size, const char* rtpInfo, uint64_t session_id) { memset((void*)buf, 0, buf_size); snprintf((char*)buf, buf_size, "RTSP/1.0 200 OK\r\n" "CSeq: %d\r\n" "Range: npt=0.000-\r\n" - "Session: %u; timeout=60\r\n", + "Session: %llu; timeout=60\r\n", this->GetCSeq(), session_id); @@ -519,7 +519,7 @@ int RtspRequest::BuildPlayRes(const char* buf, int buf_size, const char* rtpInfo return (int)strlen(buf); } -int RtspRequest::BuildTeardownRes(const char* buf, int buf_size, uint32_t session_id) +int RtspRequest::BuildTeardownRes(const char* buf, int buf_size, uint64_t session_id) { memset((void*)buf, 0, buf_size); snprintf((char*)buf, buf_size, @@ -533,7 +533,7 @@ int RtspRequest::BuildTeardownRes(const char* buf, int buf_size, uint32_t sessio return (int)strlen(buf); } -int RtspRequest::BuildGetParamterRes(const char* buf, int buf_size, uint32_t session_id) +int RtspRequest::BuildGetParamterRes(const char* buf, int buf_size, uint64_t session_id) { memset((void*)buf, 0, buf_size); snprintf((char*)buf, buf_size, diff --git a/src/xop/RtspMessage.h b/src/xop/RtspMessage.h index 3bdf5c9..e5ddfc2 100644 --- a/src/xop/RtspMessage.h +++ b/src/xop/RtspMessage.h @@ -84,13 +84,13 @@ class RtspRequest int BuildOptionRes(const char* buf, int buf_size); int BuildDescribeRes(const char* buf, int buf_size, const char* sdp); - int BuildSetupMulticastRes(const char* buf, int buf_size, const char* multicast_ip, uint16_t port, uint32_t session_id); - int BuildSetupTcpRes(const char* buf, int buf_size, uint16_t rtp_chn, uint16_t rtcp_chn, uint32_t session_id); - int BuildSetupUdpRes(const char* buf, int buf_size, uint16_t rtp_chn, uint16_t rtcp_chn, uint32_t session_id); - int BuildPlayRes(const char* buf, int buf_size, const char* rtp_info, uint32_t session_id); - int BuildTeardownRes(const char* buf, int buf_size, uint32_t session_id); + int BuildSetupMulticastRes(const char* buf, int buf_size, const char* multicast_ip, uint16_t port, uint64_t session_id); + int BuildSetupTcpRes(const char* buf, int buf_size, uint16_t rtp_chn, uint16_t rtcp_chn, uint64_t session_id); + int BuildSetupUdpRes(const char* buf, int buf_size, uint16_t rtp_chn, uint16_t rtcp_chn, uint64_t session_id); + int BuildPlayRes(const char* buf, int buf_size, const char* rtp_info, uint64_t session_id); + int BuildTeardownRes(const char* buf, int buf_size, uint64_t session_id); //int BuildTeardownMSG(const char* buf, int buf_size, uint32_t session_id); - int BuildGetParamterRes(const char* buf, int buf_size, uint32_t session_id); + int BuildGetParamterRes(const char* buf, int buf_size, uint64_t session_id); int BuildNotFoundRes(const char* buf, int buf_size); int BuildServerErrorRes(const char* buf, int buf_size); int BuildUnsupportedRes(const char* buf, int buf_size); From 2eeed4df8755d258210d84bdcff23e94ec384406 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Thu, 20 May 2021 22:39:38 +0200 Subject: [PATCH 17/21] some more debug --- src/xop/RtspConnection.cpp | 3 +- src/xop/RtspServer.cpp | 65 +++++++++++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/xop/RtspConnection.cpp b/src/xop/RtspConnection.cpp index 8df89b4..8fc61af 100644 --- a/src/xop/RtspConnection.cpp +++ b/src/xop/RtspConnection.cpp @@ -22,7 +22,7 @@ RtspConnection::RtspConnection(std::shared_ptr rtsp, TaskScheduler *task_s , rtsp_request_(new RtspRequest) , rtsp_response_(new RtspResponse) { -#ifdef RTSP_DEBUG +#if RTSP_DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspRequest Constructor"); #else @@ -83,7 +83,6 @@ bool RtspConnection::OnRead(BufferReader& buffer) if (buffer.ReadableBytes() > MAX_RTSP_MESSAGE_SIZE) { buffer.RetrieveAll(); } - return true; } diff --git a/src/xop/RtspServer.cpp b/src/xop/RtspServer.cpp index 6cacea3..3f28e47 100644 --- a/src/xop/RtspServer.cpp +++ b/src/xop/RtspServer.cpp @@ -6,25 +6,53 @@ using namespace xop; using namespace std; +#define RTSP_DEBUG 0 + RtspServer::RtspServer(EventLoop* loop) : TcpServer(loop) { - +#if RTSP_DEBUG + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspServer Constructor"); + #else + std::cout << "RtspServer Constructor" << std::endl; + #endif +#endif } RtspServer::~RtspServer() { - +#if RTSP_DEBUG + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspServer Destructor"); + #else + std::cout << "RtspServer Destructor" << std::endl; + #endif +#endif } std::shared_ptr RtspServer::Create(xop::EventLoop* loop) { +#if RTSP_DEBUG + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspServer Create"); + #else + std::cout << "RtspServer Create" << std::endl; + #endif +#endif std::shared_ptr server(new RtspServer(loop)); return server; } MediaSessionId RtspServer::AddSession(MediaSession* session) { +#if RTSP_DEBUG + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspServer AddSession"); + #else + std::cout << "RtspServer AddSession" << std::endl; + #endif +#endif std::lock_guard locker(mutex_); if (rtsp_suffix_map_.find(session->GetRtspUrlSuffix()) != rtsp_suffix_map_.end()) { @@ -41,6 +69,13 @@ MediaSessionId RtspServer::AddSession(MediaSession* session) void RtspServer::RemoveSession(MediaSessionId sessionId) { +#if RTSP_DEBUG + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspServer: RemoveSession"); + #else + std::cout << "RtspServer: RemoveSession" << std::endl; + #endif +#endif std::lock_guard locker(mutex_); auto iter = media_sessions_.find(sessionId); @@ -52,6 +87,13 @@ void RtspServer::RemoveSession(MediaSessionId sessionId) MediaSession::Ptr RtspServer::LookMediaSession(const std::string& suffix) { +#if RTSP_DEBUG + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspServer: LookMediaSession by suffix..."); + #else + std::cout << "RtspServer: LookMediaSession by suffix..." << std::endl; + #endif +#endif std::lock_guard locker(mutex_); auto iter = rtsp_suffix_map_.find(suffix); @@ -65,6 +107,13 @@ MediaSession::Ptr RtspServer::LookMediaSession(const std::string& suffix) MediaSession::Ptr RtspServer::LookMediaSession(MediaSessionId session_Id) { +#if RTSP_DEBUG + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspServer: LookMediaSession..."); + #else + std::cout << "RtspServer: LookMediaSession..." << std::endl; + #endif +#endif std::lock_guard locker(mutex_); auto iter = media_sessions_.find(session_Id); @@ -77,8 +126,14 @@ MediaSession::Ptr RtspServer::LookMediaSession(MediaSessionId session_Id) bool RtspServer::PushFrame(MediaSessionId session_id, MediaChannelId channel_id, AVFrame frame) { +#if RTSP_DEBUG + #if defined(ANDROID) + __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, "RtspServer PushFrame"); + #else + std::cout << "RtspServer PushFrame" << std::endl; + #endif +#endif std::shared_ptr sessionPtr = nullptr; - { std::lock_guard locker(mutex_); auto iter = media_sessions_.find(session_id); @@ -99,9 +154,11 @@ bool RtspServer::PushFrame(MediaSessionId session_id, MediaChannelId channel_id, TcpConnection::Ptr RtspServer::OnConnect(SOCKET sockfd) { -#if DEBUG +#if RTSP_DEBUG #if defined(ANDROID) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, "RtspServer: received connect request..."); + #else + std::cout << "RtspServer: received connect request..." << std::endl; #endif #endif return std::make_shared(shared_from_this(), event_loop_->GetTaskScheduler().get(), sockfd); From 8adead700fc4d5f9551ba7002837664be909c5b4 Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Wed, 25 Aug 2021 10:06:57 +0200 Subject: [PATCH 18/21] try/catch around stoll --- src/xop/RtspMessage.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/xop/RtspMessage.cpp b/src/xop/RtspMessage.cpp index 3c28a39..b2e4a4e 100644 --- a/src/xop/RtspMessage.cpp +++ b/src/xop/RtspMessage.cpp @@ -671,7 +671,14 @@ bool RtspResponse::ParseResponse(xop::BufferReader *buffer) if (ptr != NULL) { char session_id[50] = {0}; if (sscanf(ptr, "%*[^:]: %s", session_id) == 1) - session_ = std::stol(session_id); + try + { + session_ = std::stoll(session_id); + } + catch (const std::out_of_range& oor) + { + return false; + } } cseq_++; From 3bc6dfbb208d0fc79c14931bf909d761632e6d4d Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Wed, 25 Aug 2021 10:29:07 +0200 Subject: [PATCH 19/21] stoull --- src/xop/RtspMessage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xop/RtspMessage.cpp b/src/xop/RtspMessage.cpp index b2e4a4e..e6aa964 100644 --- a/src/xop/RtspMessage.cpp +++ b/src/xop/RtspMessage.cpp @@ -673,7 +673,7 @@ bool RtspResponse::ParseResponse(xop::BufferReader *buffer) if (sscanf(ptr, "%*[^:]: %s", session_id) == 1) try { - session_ = std::stoll(session_id); + session_ = std::stoull(session_id); } catch (const std::out_of_range& oor) { From 785cdf73f21ecc60ed1d34a664fa05226763243c Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Mon, 8 Nov 2021 21:53:36 +0100 Subject: [PATCH 20/21] update for windows build --- example/rtsp_h264_file.cpp | 4 +++ src/net/SocketUtil.cpp | 12 +++++-- src/xop/RtspMessage.cpp | 2 ++ src/xop/rtp.h | 72 ++++++++++++++++++++++---------------- 4 files changed, 58 insertions(+), 32 deletions(-) diff --git a/example/rtsp_h264_file.cpp b/example/rtsp_h264_file.cpp index 53f8462..f95874c 100644 --- a/example/rtsp_h264_file.cpp +++ b/example/rtsp_h264_file.cpp @@ -126,7 +126,11 @@ H264File::~H264File() bool H264File::Open(const char *path) { +#ifdef WIN32 + fopen_s(&m_file, path, "rb"); +#else m_file = fopen(path, "rb"); +#endif if(m_file == NULL) { return false; } diff --git a/src/net/SocketUtil.cpp b/src/net/SocketUtil.cpp index ba0e321..2c98278 100644 --- a/src/net/SocketUtil.cpp +++ b/src/net/SocketUtil.cpp @@ -113,8 +113,12 @@ void SocketUtil::SetRecvBufSize(SOCKET sockfd, int size) int SocketUtil::GetSendBufSize(SOCKET sockfd) { +#ifdef WIN32 + char optval; +#else int optval; - socklen_t optlen = sizeof(optval); +#endif + socklen_t optlen = sizeof(optval); if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) { #ifdef DEBUG #if defined(ANDROID) @@ -129,7 +133,11 @@ int SocketUtil::GetSendBufSize(SOCKET sockfd) int SocketUtil::GetRecvBufSize(SOCKET sockfd) { - int optval; +#ifdef WIN32 + char optval; +#else + int optval; +#endif socklen_t optlen = sizeof(optval); if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &optval, &optlen) < 0) { #ifdef DEBUG diff --git a/src/xop/RtspMessage.cpp b/src/xop/RtspMessage.cpp index e6aa964..41bef3d 100644 --- a/src/xop/RtspMessage.cpp +++ b/src/xop/RtspMessage.cpp @@ -4,6 +4,8 @@ #if defined(WIN32) || defined(_WIN32) #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS +#include +#define getpid _getpid #endif #endif diff --git a/src/xop/rtp.h b/src/xop/rtp.h index fd26a28..6559c1e 100644 --- a/src/xop/rtp.h +++ b/src/xop/rtp.h @@ -15,42 +15,54 @@ namespace xop { -enum TransportMode -{ - RTP_OVER_TCP = 1, - RTP_OVER_UDP = 2, - RTP_OVER_MULTICAST = 3, -}; - -typedef struct _RTP_header -{ - /* 小端序 */ - unsigned char csrc:4; - unsigned char extension:1; - unsigned char padding:1; - unsigned char version:2; - unsigned char payload:7; - unsigned char marker:1; - - unsigned short seq; - unsigned int ts; - unsigned int ssrc; -} RtpHeader; + enum TransportMode + { + RTP_OVER_TCP = 1, + RTP_OVER_UDP = 2, + RTP_OVER_MULTICAST = 3, + }; + typedef struct _RTP_header + { + /* 小端序 */ + unsigned char csrc : 4; + unsigned char extension : 1; + unsigned char padding : 1; + unsigned char version : 2; + unsigned char payload : 7; + unsigned char marker : 1; + + unsigned short seq; + unsigned int ts; + unsigned int ssrc; + } RtpHeader; + +#ifdef WIN32 +#pragma pack(push,1) +#endif //=============== TAKEN FROM https://github.com/sipwise/rtpengine struct rtcp_header { - unsigned count:5; /**< varies by payload type */ - unsigned p:1; /**< padding flag */ - unsigned version:2; /**< packet type */ - unsigned char pt; - uint16_t length; -} __attribute__ ((packed)); + unsigned count : 5; /**< varies by payload type */ + unsigned p : 1; /**< padding flag */ + unsigned version : 2; /**< packet type */ + unsigned char pt; + uint16_t length; +#ifndef WIN32 +} __attribute__((packed)); +#else +}; +#endif struct rtcp_packet { - struct rtcp_header header; - uint32_t ssrc; -} __attribute__ ((packed)); + struct rtcp_header header; + uint32_t ssrc; +#ifndef WIN32 +} __attribute__((packed)); +#else +}; +#pragma pack(pop) +#endif //=============================== From 38fb0ddc1533695b1a996e47035369f5a515683b Mon Sep 17 00:00:00 2001 From: Clemens Arth Date: Mon, 8 Nov 2021 23:26:42 +0100 Subject: [PATCH 21/21] Windows build --- example/rtsp_pusher.cpp | 4 ++++ example/rtsp_server.cpp | 6 +++++- src/net/BufferReader.cpp | 2 -- src/net/BufferReader.h | 6 ++++-- src/net/BufferWriter.h | 2 +- src/net/EventLoop.h | 2 +- src/net/Logger.h | 12 +++++++++++- src/net/Socket.h | 8 ++++++++ src/net/SocketUtil.h | 2 +- src/net/TaskScheduler.h | 2 +- src/net/TcpConnection.h | 2 +- src/net/TcpServer.h | 2 +- src/net/TcpSocket.h | 2 +- src/xop/DigestAuthenticator.h | 2 +- src/xop/H264Source.h | 2 +- src/xop/MediaSession.h | 2 +- src/xop/RtspPusher.h | 2 +- src/xop/RtspServer.h | 2 +- src/xop/rtsp.h | 2 +- 19 files changed, 45 insertions(+), 19 deletions(-) diff --git a/example/rtsp_pusher.cpp b/example/rtsp_pusher.cpp index e1316e1..18f3b66 100755 --- a/example/rtsp_pusher.cpp +++ b/example/rtsp_pusher.cpp @@ -176,7 +176,11 @@ H264File::~H264File() bool H264File::Open(const char *path) { +#if WIN32 + errno_t err = fopen_s(&m_file, path, "rb"); +#else m_file = fopen(path, "rb"); +#endif if(m_file == NULL) { return false; } diff --git a/example/rtsp_server.cpp b/example/rtsp_server.cpp index e0edd4d..ddebe2a 100755 --- a/example/rtsp_server.cpp +++ b/example/rtsp_server.cpp @@ -163,7 +163,11 @@ H264File::~H264File() bool H264File::Open(const char *path) { - m_file = fopen(path, "rb"); +#if WIN32 + errno_t err = fopen_s(&m_file, path, "rb"); +#else + m_file = fopen(path, "rb"); +#endif if(m_file == NULL) { return false; } diff --git a/src/net/BufferReader.cpp b/src/net/BufferReader.cpp index b94ad98..deb8594 100644 --- a/src/net/BufferReader.cpp +++ b/src/net/BufferReader.cpp @@ -48,8 +48,6 @@ uint16_t xop::ReadUint16LE(char* data) return value; } -const char BufferReader::kCRLF[] = "\r\n"; - BufferReader::BufferReader(uint32_t initial_size) { buffer_.resize(initial_size); diff --git a/src/net/BufferReader.h b/src/net/BufferReader.h index fe91437..71501af 100644 --- a/src/net/BufferReader.h +++ b/src/net/BufferReader.h @@ -21,7 +21,7 @@ uint32_t ReadUint24LE(char* data); uint16_t ReadUint16BE(char* data); uint16_t ReadUint16LE(char* data); -class BufferReader +class DLL_API BufferReader { public: BufferReader(uint32_t initial_size = 2048); @@ -40,11 +40,13 @@ class BufferReader { return Begin() + reader_index_; } const char* FindFirstCrlf() const { + char kCRLF[] = "\r\n"; const char* crlf = std::search(Peek(), BeginWrite(), kCRLF, kCRLF+2); return crlf == BeginWrite() ? nullptr : crlf; } const char* FindLastCrlf() const { + char kCRLF[] = "\r\n"; const char* crlf = std::find_end(Peek(), BeginWrite(), kCRLF, kCRLF+2); return crlf == BeginWrite() ? nullptr : crlf; } @@ -84,6 +86,7 @@ class BufferReader { return (uint32_t)buffer_.size(); } private: + char* Begin() { return &*buffer_.begin(); } @@ -100,7 +103,6 @@ class BufferReader size_t reader_index_ = 0; size_t writer_index_ = 0; - static const char kCRLF[]; static const uint32_t MAX_BYTES_PER_READ = 4096; static const uint32_t MAX_BUFFER_SIZE = 1024 * 100000; }; diff --git a/src/net/BufferWriter.h b/src/net/BufferWriter.h index c4f92b4..2bcbad3 100644 --- a/src/net/BufferWriter.h +++ b/src/net/BufferWriter.h @@ -20,7 +20,7 @@ void WriteUint24LE(char* p, uint32_t value); void WriteUint16BE(char* p, uint16_t value); void WriteUint16LE(char* p, uint16_t value); -class BufferWriter +class DLL_API BufferWriter { public: BufferWriter(int capacity = kMaxQueueLength); diff --git a/src/net/EventLoop.h b/src/net/EventLoop.h index f11a1d8..60ea62b 100644 --- a/src/net/EventLoop.h +++ b/src/net/EventLoop.h @@ -27,7 +27,7 @@ namespace xop { -class EventLoop +class DLL_API EventLoop { public: EventLoop(const EventLoop&) = delete; diff --git a/src/net/Logger.h b/src/net/Logger.h index 74fcb07..a08bc7c 100644 --- a/src/net/Logger.h +++ b/src/net/Logger.h @@ -12,6 +12,16 @@ #include #include +#if(WIN32) +#ifdef DLL_EXPORTS +#define DLL_API __declspec(dllexport) +#else +#define DLL_API __declspec(dllimport) +#endif +#else +#define DLL_API +#endif + namespace xop { @@ -20,7 +30,7 @@ enum Priority LOG_DEBUG, LOG_STATE, LOG_INFO, LOG_WARNING, LOG_ERROR, }; -class Logger +class DLL_API Logger { public: Logger &operator=(const Logger &) = delete; diff --git a/src/net/Socket.h b/src/net/Socket.h index d3d099f..2da6328 100644 --- a/src/net/Socket.h +++ b/src/net/Socket.h @@ -26,6 +26,8 @@ #define INVALID_SOCKET (-1) #define SOCKET_ERROR (-1) +#define DLL_API + #elif defined(WIN32) || defined(_WIN32) #define FD_SETSIZE 1024 #define WIN32_LEAN_AND_MEAN @@ -38,6 +40,12 @@ #define SHUT_WR 1 #define SHUT_RDWR 2 +#ifdef DLL_EXPORTS +#define DLL_API __declspec(dllexport) +#else +#define DLL_API __declspec(dllimport) +#endif + #else #endif diff --git a/src/net/SocketUtil.h b/src/net/SocketUtil.h index f161309..0a990c5 100644 --- a/src/net/SocketUtil.h +++ b/src/net/SocketUtil.h @@ -10,7 +10,7 @@ namespace xop { -class SocketUtil +class DLL_API SocketUtil { public: static bool Bind(SOCKET sockfd, std::string ip, uint16_t port); diff --git a/src/net/TaskScheduler.h b/src/net/TaskScheduler.h index ff6fd01..451717c 100644 --- a/src/net/TaskScheduler.h +++ b/src/net/TaskScheduler.h @@ -14,7 +14,7 @@ namespace xop typedef std::function TriggerEvent; -class TaskScheduler +class DLL_API TaskScheduler { public: TaskScheduler(int id=1); diff --git a/src/net/TcpConnection.h b/src/net/TcpConnection.h index 97c244d..1b1e8ad 100644 --- a/src/net/TcpConnection.h +++ b/src/net/TcpConnection.h @@ -12,7 +12,7 @@ namespace xop { -class TcpConnection : public std::enable_shared_from_this +class DLL_API TcpConnection : public std::enable_shared_from_this { public: using Ptr = std::shared_ptr; diff --git a/src/net/TcpServer.h b/src/net/TcpServer.h index 78f37ae..bed3493 100644 --- a/src/net/TcpServer.h +++ b/src/net/TcpServer.h @@ -17,7 +17,7 @@ namespace xop class Acceptor; class EventLoop; -class TcpServer +class DLL_API TcpServer { public: TcpServer(EventLoop* event_loop); diff --git a/src/net/TcpSocket.h b/src/net/TcpSocket.h index ace8776..cab45e3 100644 --- a/src/net/TcpSocket.h +++ b/src/net/TcpSocket.h @@ -11,7 +11,7 @@ namespace xop { -class TcpSocket +class DLL_API TcpSocket { public: TcpSocket(SOCKET sockfd=-1); diff --git a/src/xop/DigestAuthenticator.h b/src/xop/DigestAuthenticator.h index e3d20f3..281616c 100644 --- a/src/xop/DigestAuthenticator.h +++ b/src/xop/DigestAuthenticator.h @@ -12,7 +12,7 @@ namespace xop { -class DigestAuthenticator : public Authenticator +class DLL_API DigestAuthenticator : public Authenticator { public: DigestAuthenticator(std::string realm, std::string username, std::string password); diff --git a/src/xop/H264Source.h b/src/xop/H264Source.h index 2622159..e26fea8 100644 --- a/src/xop/H264Source.h +++ b/src/xop/H264Source.h @@ -10,7 +10,7 @@ namespace xop { -class H264Source : public MediaSource +class DLL_API H264Source : public MediaSource { public: static H264Source* CreateNew(uint32_t framerate=25); diff --git a/src/xop/MediaSession.h b/src/xop/MediaSession.h index 48814b7..fb90ab2 100644 --- a/src/xop/MediaSession.h +++ b/src/xop/MediaSession.h @@ -26,7 +26,7 @@ namespace xop class RtpConnection; -class MediaSession +class DLL_API MediaSession { public: using Ptr = std::shared_ptr; diff --git a/src/xop/RtspPusher.h b/src/xop/RtspPusher.h index 566f7bf..c5f75c2 100644 --- a/src/xop/RtspPusher.h +++ b/src/xop/RtspPusher.h @@ -10,7 +10,7 @@ namespace xop class RtspConnection; -class RtspPusher : public Rtsp +class DLL_API RtspPusher : public Rtsp { public: static std::shared_ptr Create(xop::EventLoop* loop); diff --git a/src/xop/RtspServer.h b/src/xop/RtspServer.h index 2806203..e7eaa22 100644 --- a/src/xop/RtspServer.h +++ b/src/xop/RtspServer.h @@ -16,7 +16,7 @@ namespace xop class RtspConnection; -class RtspServer : public Rtsp, public TcpServer +class DLL_API RtspServer : public Rtsp, public TcpServer { public: static std::shared_ptr Create(xop::EventLoop* loop); diff --git a/src/xop/rtsp.h b/src/xop/rtsp.h index 758a629..190af00 100644 --- a/src/xop/rtsp.h +++ b/src/xop/rtsp.h @@ -31,7 +31,7 @@ struct RtspUrlInfo std::string suffix; }; -class Rtsp : public std::enable_shared_from_this +class DLL_API Rtsp : public std::enable_shared_from_this { public: Rtsp() : has_auth_info_(false), authenticator_(nullptr) {}