first commit
This commit is contained in:
24
third_party/rtsp_server/CMakeLists.txt
vendored
Normal file
24
third_party/rtsp_server/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(rtsp_server VERSION 1.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fPIC -w -fdiagnostics-color=always -pthread")
|
||||
|
||||
# Gstreamer required
|
||||
include(FindPkgConfig)
|
||||
pkg_check_modules(GST REQUIRED gstreamer-1.0)
|
||||
pkg_check_modules(GSTAPP REQUIRED gstreamer-app-1.0)
|
||||
pkg_check_modules(GST_RTSP REQUIRED gstreamer-rtsp-server-1.0)
|
||||
message(STATUS "GStreamer library status:")
|
||||
message(STATUS " version: ${GST_VERSION}")
|
||||
message(STATUS " libraries: ${GST_LIBRARIES} ${GSTAPP_LIBRARIES} ${GST_RTSP_LIBRARIES}")
|
||||
message(STATUS " include path: ${GST_INCLUDE_DIRS}")
|
||||
include_directories(${GST_INCLUDE_DIRS})
|
||||
set(GST_DEPEND_LIBS ${GST_LIBRARIES} ${GSTAPP_LIBRARIES} ${GST_RTSP_LIBRARIES})
|
||||
|
||||
|
||||
# build for rtsp_server
|
||||
file(GLOB SRCS "run_rtsp_server.cpp")
|
||||
add_executable(run_rtsp_server ${SRCS})
|
||||
target_link_libraries(run_rtsp_server ${GST_DEPEND_LIBS})
|
||||
56
third_party/rtsp_server/README.md
vendored
Normal file
56
third_party/rtsp_server/README.md
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
# rtsp_server #
|
||||
|
||||
> NOTE: building of VideoPipe is not dependent on this project.
|
||||
|
||||
a simple rtsp server based on `GStreamer` which can accept udp stream and distribute them using `rtsp` protocal something like `rtsp://127.0.0.1:8554/stream1`/`rtsp://127.0.0.1:8554/stream2`.
|
||||
|
||||
|
||||
## how to build ##
|
||||
|
||||
first install `GStreamer` refer to `VideoPipe`, and build using CMake:
|
||||
|
||||
```
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make -j8
|
||||
|
||||
```
|
||||
|
||||
## how to run ##
|
||||
first build `rtsp_server` successfully and run:
|
||||
|
||||
`./build/run_rtsp_server [-p] [rtsp_port] [-s] [stream_name1:inner_port1/stream_name2:inner_port2/...]`
|
||||
```
|
||||
for example:
|
||||
./build/run_rtsp_server -p 8555 -s rtsp0:8000/rtsp1:9000/rtsp2:9005
|
||||
|
||||
rtsp server will listen at ports(8000/9000/9005) to receive udp stream and distribute them at port 8555 using rtsp protocal:
|
||||
########## rtsp server info ###########
|
||||
(1) rtsp0==>8000==>rtsp://127.0.0.1:8555/rtsp0
|
||||
(2) rtsp1==>9000==>rtsp://127.0.0.1:8555/rtsp1
|
||||
(3) rtsp2==>9005==>rtsp://127.0.0.1:8555/rtsp2
|
||||
```
|
||||
|
||||
then you need push your stream to port `8000`, `9000`, `9005` using some multi-media tools like `gst-launch-1.0` or your application.
|
||||
|
||||
```
|
||||
# push udp stream to port 8000
|
||||
gst-launch-1.0 filesrc location=face2.mp4 ! qtdemux ! h264parse ! avdec_h264 ! x264enc ! rtph264pay ! udpsink host=localhost port=8000
|
||||
|
||||
# push udp stream to port 9000
|
||||
gst-launch-1.0 filesrc location=face2.mp4 ! qtdemux ! h264parse ! avdec_h264 ! x264enc ! rtph264pay ! udpsink host=localhost port=9000
|
||||
|
||||
# push udp stream to port 9005
|
||||
gst-launch-1.0 filesrc location=face2.mp4 ! qtdemux ! h264parse ! avdec_h264 ! x264enc ! rtph264pay ! udpsink host=localhost port=9005
|
||||
```
|
||||
|
||||
now you can pull/play rtsp stream using `vlc` or `gst-launch-1.0` by rtsp urls:
|
||||
```
|
||||
rtsp://127.0.0.1:8555/rtsp0
|
||||
rtsp://127.0.0.1:8555/rtsp1
|
||||
rtsp://127.0.0.1:8555/rtsp2
|
||||
```
|
||||
|
||||
## how rtsp_server serve VideoPipe? ##
|
||||
|
||||
`vp_udp_des_node` in VideoPipe will push udp streams to rtsp_server, which distribute them by rtsp protocal.
|
||||
119
third_party/rtsp_server/run_rtsp_server.cpp
vendored
Normal file
119
third_party/rtsp_server/run_rtsp_server.cpp
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <gst/gst.h>
|
||||
#include <gst/rtsp-server/rtsp-server.h>
|
||||
|
||||
inline std::vector<std::string> string_split(const std::string& s, char delimiter) {
|
||||
std::vector<std::string> tokens;
|
||||
std::string token;
|
||||
std::istringstream tokenStream(s);
|
||||
while (std::getline(tokenStream, token, delimiter)) {
|
||||
tokens.push_back(token);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/*
|
||||
* usage:
|
||||
* ./run_rtsp_server [-p] [rtsp_port] [-s] [stream_name1:inner_port1/stream_name2:inner_port2/...]
|
||||
*
|
||||
* for example:
|
||||
* ./run_rtsp_server -p 8554 -s 1st_rtsp:8000/2nd_rtsp:8001/3rd_rtsp:8002
|
||||
* rtsp server will listen at ports(8000/8001/8002) to receive udp stream and distribute them at port 8554 using rtsp protocal:
|
||||
* (1) rtsp://127.0.0.1:8554/1st_rtsp
|
||||
* (2) rtsp://127.0.0.1:8554/2nd_rtsp
|
||||
* (3) rtsp://127.0.0.1:8554/3rd_rtsp
|
||||
*/
|
||||
bool parse_args(int argc, char** argv, std::string& rtsp_port, std::vector<std::pair<std::string, std::string>>& streams_info) {
|
||||
auto print_error = []() {
|
||||
std::cout << "invalid arguments!" << std::endl;
|
||||
std::cout << "./run_rtsp_server [-p] [rtsp_port] [-s] [stream_name1:inner_port1/stream_name2:inner_port2/...]" << std::endl;
|
||||
};
|
||||
|
||||
if (argc != 5) {
|
||||
print_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto _p = std::string(argv[1]);
|
||||
rtsp_port = std::string(argv[2]);
|
||||
auto _s = std::string(argv[3]);
|
||||
auto streams = std::string(argv[4]);
|
||||
|
||||
if (_p != "-p" || _s != "-s") {
|
||||
print_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto streams_list = string_split(streams, '/');
|
||||
for (auto& stream: streams_list) {
|
||||
auto name_port = string_split(stream, ':');
|
||||
if (name_port.size() != 2) {
|
||||
print_error();
|
||||
return false;
|
||||
}
|
||||
streams_info.push_back(std::pair<std::string, std::string>(name_port[0], name_port[1]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::string rtsp_port;
|
||||
std::vector<std::pair<std::string, std::string>> streams_info;
|
||||
if (!parse_args(argc, argv, rtsp_port, streams_info)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto rtsp_server_run = [&]() {
|
||||
GMainLoop* loop;
|
||||
GstRTSPServer* server;
|
||||
|
||||
gst_init(&argc, &argv);
|
||||
server = gst_rtsp_server_new();
|
||||
g_object_set(server, "service", rtsp_port.c_str(), NULL);
|
||||
gst_rtsp_server_attach(server, NULL);
|
||||
auto mounts = gst_rtsp_server_get_mount_points(server);
|
||||
|
||||
for(auto& stream: streams_info) {
|
||||
auto stream_name = stream.first;
|
||||
auto stream_port = stream.second;
|
||||
|
||||
char udpsrc_pipeline[512];
|
||||
int udp_buffer_size = 512 * 1024;
|
||||
|
||||
// receive stream data from udpsrc internally and push it via rtsp
|
||||
sprintf (udpsrc_pipeline,
|
||||
"( udpsrc name=pay0 port=%s buffer-size=%lu caps=\"application/x-rtp, media=video, "
|
||||
"clock-rate=90000, encoding-name=H264, payload=96 \" )",
|
||||
stream_port.c_str(), udp_buffer_size);
|
||||
|
||||
auto factory = gst_rtsp_media_factory_new();
|
||||
gst_rtsp_media_factory_set_launch(factory, udpsrc_pipeline);
|
||||
gst_rtsp_media_factory_set_shared(factory, true);
|
||||
gst_rtsp_mount_points_add_factory(mounts, ("/" + stream_name).c_str(), factory);
|
||||
}
|
||||
g_object_unref(mounts);
|
||||
|
||||
std::cout << "########## rtsp server info ###########" << std::endl;
|
||||
for (int i = 0; i < streams_info.size(); i++) {
|
||||
std::cout << "(" << i + 1 << ") "
|
||||
<< streams_info[i].first << "==>" << streams_info[i].second
|
||||
<< "==>rtsp://127.0.0.1:" << rtsp_port << "/" << streams_info[i].first << std::endl;
|
||||
}
|
||||
|
||||
loop = g_main_loop_new(NULL, FALSE);
|
||||
g_main_loop_run(loop);
|
||||
g_main_loop_unref(loop);
|
||||
gst_object_unref(server);
|
||||
};
|
||||
std::thread rtsp_server(rtsp_server_run);
|
||||
|
||||
// enter to exit
|
||||
std::string wait;
|
||||
std::getline(std::cin, wait);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user