mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
优化tcp推流
This commit is contained in:
commit
4ea1fd8d76
@ -180,8 +180,9 @@ if (WIN32)
|
||||
set(INSTALL_PATH_LIB $ENV{HOME}/${CMAKE_PROJECT_NAME}/lib)
|
||||
set(INSTALL_PATH_INCLUDE $ENV{HOME}/${CMAKE_PROJECT_NAME}/include)
|
||||
else ()
|
||||
set(INSTALL_PATH_LIB lib)
|
||||
set(INSTALL_PATH_LIB lib${LIB_SUFFIX})
|
||||
set(INSTALL_PATH_INCLUDE include)
|
||||
set(INSTALL_PATH_EXECUTABLE bin)
|
||||
endif ()
|
||||
|
||||
if(ENABLE_CXX_API)
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
## 功能清单
|
||||
### 功能一览
|
||||
<img width="800" alt="图片" src="https://user-images.githubusercontent.com/11495632/93857284-f15b5f00-fcec-11ea-894d-83eb656dc235.png">
|
||||
<img width="800" alt="图片" src="https://user-images.githubusercontent.com/11495632/102689561-09824200-423a-11eb-9cf9-b39d1378ef68.png">
|
||||
|
||||
- RTSP[S]
|
||||
- RTSP[S] 服务器,支持RTMP/MP4/HLS转RTSP[S],支持亚马逊echo show这样的设备
|
||||
@ -140,7 +140,7 @@ bash build_docker_images.sh
|
||||
|
||||
- 流媒体管理平台
|
||||
- [功能强大的流媒体控制管理接口平台,支持GB28181](https://github.com/chatop2020/StreamNode)
|
||||
- [GB28181-2016网络视频平台](https://github.com/648540858/wvp-GB28181)
|
||||
- [GB28181-2016网络视频平台](https://github.com/648540858/wvp-GB28181-pro)
|
||||
- [node-js版本的GB28181平台](https://gitee.com/hfwudao/GB28181_Node_Http)
|
||||
- [Go实现的海康ehome服务器](https://github.com/tsingeye/FreeEhome)
|
||||
|
||||
|
@ -55,7 +55,7 @@ modifyStamp=0
|
||||
#服务器唯一id,用于触发hook时区别是哪台服务器
|
||||
mediaServerId=your_server_id
|
||||
|
||||
###### 以下是按需转协议的开关,在测试ZLMediaKit的接收推流性能时,请关闭以下全部开关
|
||||
###### 以下是按需转协议的开关,在测试ZLMediaKit的接收推流性能时,请把下面开关置1
|
||||
###### 如果某种协议你用不到,你可以把以下开关置1以便节省资源(但是还是可以播放,只是第一个播放者体验稍微差点),
|
||||
###### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
|
||||
|
||||
|
142
package/rpm/ZLMediaKit.spec
Normal file
142
package/rpm/ZLMediaKit.spec
Normal file
@ -0,0 +1,142 @@
|
||||
%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7
|
||||
%global use_devtoolset 0
|
||||
%bcond_without faac
|
||||
%bcond_without x264
|
||||
%else
|
||||
%global use_devtoolset 1
|
||||
%bcond_with faac
|
||||
%bcond_with x264
|
||||
%endif
|
||||
|
||||
%bcond_without openssl
|
||||
%bcond_without mysql
|
||||
|
||||
Name: ZLMediaKit
|
||||
Version: 5.0.0
|
||||
Release: 1%{?dist}
|
||||
Summary: A lightweight, high performance and stable stream server and client framework based on C++11.
|
||||
|
||||
Group: development
|
||||
License: MIT
|
||||
URL: https://github.com/xia-chu/ZLMediaKit
|
||||
Source0: %{name}-%{version}.tar.xz
|
||||
|
||||
%if %{with openssl}
|
||||
BuildRequires: openssl-devel
|
||||
%endif
|
||||
|
||||
%if %{with mysql}
|
||||
BuildRequires: mysql-devel
|
||||
%endif
|
||||
|
||||
%if %{with faac}
|
||||
BuildRequires: faac-devel
|
||||
%endif
|
||||
|
||||
%if %{with x264}
|
||||
BuildRequires: x264-devel
|
||||
%endif
|
||||
|
||||
%if 0%{?use_devtoolset}
|
||||
BuildRequires: devtoolset-8-gcc-c++
|
||||
%endif
|
||||
|
||||
%description
|
||||
A lightweight RTSP/RTMP/HTTP/HLS/HTTP-FLV/WebSocket-FLV/HTTP-TS/HTTP-fMP4/WebSocket-TS/WebSocket-fMP4/GB28181 server and client framework based on C++11.
|
||||
|
||||
%package media-server
|
||||
Requires: %{name} = %{version}
|
||||
Summary: A lightweight, high performance and stable stream server
|
||||
|
||||
%description media-server
|
||||
A lightweight RTSP/RTMP/HTTP/HLS/HTTP-FLV/WebSocket-FLV/HTTP-TS/HTTP-fMP4/WebSocket-TS/WebSocket-fMP4/GB28181 server.
|
||||
|
||||
%package c-libs
|
||||
Requires: %{name} = %{version}
|
||||
Summary: The %{name} C libraries.
|
||||
%description c-libs
|
||||
The %{name} C libraries.
|
||||
|
||||
%package c-devel
|
||||
Requires: %{name}-c-libs = %{version}
|
||||
Summary: The %{name} C API headers.
|
||||
%description c-devel
|
||||
The %{name} C API headers.
|
||||
|
||||
%package cxx-devel
|
||||
Requires: %{name} = %{version}
|
||||
Summary: The %{name} C++ API headers and development libraries.
|
||||
%description cxx-devel
|
||||
The %{name} C++ API headers and development libraries.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
mkdir -p %{_target_platform}
|
||||
|
||||
pushd %{_target_platform}
|
||||
|
||||
%if 0%{?use_devtoolset}
|
||||
. /opt/rh/devtoolset-8/enable
|
||||
%endif
|
||||
|
||||
%cmake3 \
|
||||
-DCMAKE_BUILD_TYPE:STRING=Release \
|
||||
-DENABLE_HLS:BOOL=ON \
|
||||
-DENABLE_OPENSSL:BOOL=%{with openssl} \
|
||||
-DENABLE_MYSQL:BOOL=%{with mysql} \
|
||||
-DENABLE_FAAC:BOOL=%{with faac} \
|
||||
-DENABLE_X264:BOOL=%{with x264} \
|
||||
-DENABLE_MP4:BOOL=ON \
|
||||
-DENABLE_RTPPROXY:BOOL=ON \
|
||||
-DENABLE_API:BOOL=ON \
|
||||
-DENABLE_CXX_API:BOOL=ON \
|
||||
-DENABLE_TESTS:BOOL=OFF \
|
||||
-DENABLE_SERVERL:BOOL=ON \
|
||||
..
|
||||
|
||||
make %{?_smp_mflags}
|
||||
|
||||
popd
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
pushd %{_target_platform}
|
||||
%make_install
|
||||
popd
|
||||
|
||||
install -m 0755 -d %{buildroot}%{_docdir}/%{name}
|
||||
install -m 0644 LICENSE %{buildroot}%{_docdir}/%{name}
|
||||
install -m 0644 README.md %{buildroot}%{_docdir}/%{name}
|
||||
install -m 0644 README_en.md %{buildroot}%{_docdir}/%{name}
|
||||
|
||||
# TODO: service files
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%doc %{_docdir}/*
|
||||
|
||||
%files media-server
|
||||
%{_bindir}/*
|
||||
|
||||
%files c-libs
|
||||
%{_libdir}/libmk_api.so
|
||||
|
||||
%files c-devel
|
||||
%{_includedir}/mk_*
|
||||
|
||||
%files cxx-devel
|
||||
%{_includedir}/ZLMediaKit/*
|
||||
%{_includedir}/ZLToolKit/*
|
||||
%{_libdir}/libzlmediakit.a
|
||||
%{_libdir}/libzltoolkit.a
|
||||
%{_libdir}/libmpeg.a
|
||||
%{_libdir}/libmov.a
|
||||
%{_libdir}/libflv.a
|
||||
|
||||
%changelog
|
||||
|
@ -428,7 +428,7 @@
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{ZLMediaKit_URL}}/index/api/addStreamProxy?secret={{ZLMediaKit_secret}}&vhost={{defaultVhost}}&app=live&stream=test&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2&enable_rtsp=1&enable_rtmp=1",
|
||||
"raw": "{{ZLMediaKit_URL}}/index/api/addStreamProxy?secret={{ZLMediaKit_secret}}&vhost={{defaultVhost}}&app=live&stream=test&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2",
|
||||
"host": [
|
||||
"{{ZLMediaKit_URL}}"
|
||||
],
|
||||
@ -523,7 +523,7 @@
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{ZLMediaKit_URL}}/index/api/addFFmpegSource?secret={{ZLMediaKit_secret}}&src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://10.8.9.115:8554/live/hks2&timeout_ms=10000",
|
||||
"raw": "{{ZLMediaKit_URL}}/index/api/addFFmpegSource?secret={{ZLMediaKit_secret}}&src_url=http://hefeng.live.tempsource.cjyun.org/videotmp/s10100-hftv.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000&enable_hls=0&enable_mp4=0",
|
||||
"host": [
|
||||
"{{ZLMediaKit_URL}}"
|
||||
],
|
||||
@ -540,7 +540,7 @@
|
||||
},
|
||||
{
|
||||
"key": "src_url",
|
||||
"value": "http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8",
|
||||
"value": "http://hefeng.live.tempsource.cjyun.org/videotmp/s10100-hftv.m3u8",
|
||||
"description": "FFmpeg拉流地址,支持任意协议或格式(只要FFmpeg支持即可)"
|
||||
},
|
||||
{
|
||||
@ -552,6 +552,16 @@
|
||||
"key": "timeout_ms",
|
||||
"value": "10000",
|
||||
"description": "FFmpeg推流成功超时时间,单位毫秒"
|
||||
},
|
||||
{
|
||||
"key": "enable_hls",
|
||||
"value": "0",
|
||||
"description": "是否开启hls录制"
|
||||
},
|
||||
{
|
||||
"key": "enable_mp4",
|
||||
"value": "0",
|
||||
"description": "是否开启mp4录制"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ add_executable(MediaServer ${MediaServer_src_list})
|
||||
|
||||
if(WIN32)
|
||||
set_target_properties(MediaServer PROPERTIES COMPILE_FLAGS ${VS_FALGS} )
|
||||
else()
|
||||
install(TARGETS MediaServer DESTINATION ${INSTALL_PATH_EXECUTABLE})
|
||||
endif()
|
||||
|
||||
target_link_libraries(MediaServer jsoncpp ${LINK_LIB_LIST})
|
||||
|
||||
|
||||
|
@ -59,6 +59,11 @@ static bool is_local_ip(const string &ip){
|
||||
return false;
|
||||
}
|
||||
|
||||
void FFmpegSource::setupRecord(bool enable_hls, bool enable_mp4){
|
||||
_enable_hls = enable_hls;
|
||||
_enable_mp4 = enable_mp4;
|
||||
}
|
||||
|
||||
void FFmpegSource::play(const string &src_url,const string &dst_url,int timeout_ms,const onPlay &cb) {
|
||||
GET_CONFIG(string,ffmpeg_bin,FFmpeg::kBin);
|
||||
GET_CONFIG(string,ffmpeg_cmd,FFmpeg::kCmd);
|
||||
@ -263,6 +268,12 @@ void FFmpegSource::onGetMediaSource(const MediaSource::Ptr &src) {
|
||||
//防止多次进入onGetMediaSource函数导致无限递归调用的bug
|
||||
setDelegate(listener);
|
||||
src->setListener(shared_from_this());
|
||||
if (_enable_hls) {
|
||||
src->setupRecord(Recorder::type_hls, true, "");
|
||||
}
|
||||
if (_enable_mp4) {
|
||||
src->setupRecord(Recorder::type_mp4, true, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,13 +46,29 @@ public:
|
||||
typedef function<void(const SockException &ex)> onPlay;
|
||||
|
||||
FFmpegSource();
|
||||
virtual ~FFmpegSource();
|
||||
~FFmpegSource();
|
||||
|
||||
/**
|
||||
* 设置主动关闭回调
|
||||
* @param cb
|
||||
*/
|
||||
void setOnClose(const function<void()> &cb);
|
||||
void play(const string &src_url,const string &dst_url,int timeout_ms,const onPlay &cb);
|
||||
|
||||
/**
|
||||
* 开始播放url
|
||||
* @param src_url FFmpeg拉流地址
|
||||
* @param dst_url FFmpeg推流地址
|
||||
* @param timeout_ms 等待结果超时时间,单位毫秒
|
||||
* @param cb 成功与否回调
|
||||
*/
|
||||
void play(const string &src_url, const string &dst_url, int timeout_ms, const onPlay &cb);
|
||||
|
||||
/**
|
||||
* 设置录制
|
||||
* @param enable_hls 是否开启hls直播或录制
|
||||
* @param enable_mp4 是否录制mp4
|
||||
*/
|
||||
void setupRecord(bool enable_hls, bool enable_mp4);
|
||||
|
||||
private:
|
||||
void findAsync(int maxWaitMS ,const function<void(const MediaSource::Ptr &src)> &cb);
|
||||
void startTimer(int timeout_ms);
|
||||
@ -69,6 +85,8 @@ private:
|
||||
std::shared_ptr<SockInfo> getOriginSock(MediaSource &sender) const override;
|
||||
|
||||
private:
|
||||
bool _enable_hls = false;
|
||||
bool _enable_mp4 = false;
|
||||
Process _process;
|
||||
Timer::Ptr _timer;
|
||||
EventPoller::Ptr _poller;
|
||||
|
@ -830,28 +830,31 @@ void installWebApi() {
|
||||
static auto addFFmpegSource = [](const string &src_url,
|
||||
const string &dst_url,
|
||||
int timeout_ms,
|
||||
const function<void(const SockException &ex,const string &key)> &cb){
|
||||
bool enable_hls,
|
||||
bool enable_mp4,
|
||||
const function<void(const SockException &ex, const string &key)> &cb) {
|
||||
auto key = MD5(dst_url).hexdigest();
|
||||
lock_guard<decltype(s_ffmpegMapMtx)> lck(s_ffmpegMapMtx);
|
||||
if(s_ffmpegMap.find(key) != s_ffmpegMap.end()){
|
||||
if (s_ffmpegMap.find(key) != s_ffmpegMap.end()) {
|
||||
//已经在拉流了
|
||||
cb(SockException(Err_success),key);
|
||||
cb(SockException(Err_success), key);
|
||||
return;
|
||||
}
|
||||
|
||||
FFmpegSource::Ptr ffmpeg = std::make_shared<FFmpegSource>();
|
||||
s_ffmpegMap[key] = ffmpeg;
|
||||
|
||||
ffmpeg->setOnClose([key](){
|
||||
ffmpeg->setOnClose([key]() {
|
||||
lock_guard<decltype(s_ffmpegMapMtx)> lck(s_ffmpegMapMtx);
|
||||
s_ffmpegMap.erase(key);
|
||||
});
|
||||
ffmpeg->play(src_url, dst_url,timeout_ms,[cb , key](const SockException &ex){
|
||||
if(ex){
|
||||
ffmpeg->setupRecord(enable_hls, enable_mp4);
|
||||
ffmpeg->play(src_url, dst_url, timeout_ms, [cb, key](const SockException &ex) {
|
||||
if (ex) {
|
||||
lock_guard<decltype(s_ffmpegMapMtx)> lck(s_ffmpegMapMtx);
|
||||
s_ffmpegMap.erase(key);
|
||||
}
|
||||
cb(ex,key);
|
||||
cb(ex, key);
|
||||
});
|
||||
};
|
||||
|
||||
@ -863,12 +866,15 @@ void installWebApi() {
|
||||
auto src_url = allArgs["src_url"];
|
||||
auto dst_url = allArgs["dst_url"];
|
||||
int timeout_ms = allArgs["timeout_ms"];
|
||||
auto enable_hls = allArgs["enable_hls"].as<int>();
|
||||
auto enable_mp4 = allArgs["enable_mp4"].as<int>();
|
||||
|
||||
addFFmpegSource(src_url,dst_url,timeout_ms,[invoker,val,headerOut](const SockException &ex,const string &key){
|
||||
if(ex){
|
||||
addFFmpegSource(src_url, dst_url, timeout_ms, enable_hls, enable_mp4,
|
||||
[invoker, val, headerOut](const SockException &ex, const string &key) {
|
||||
if (ex) {
|
||||
const_cast<Value &>(val)["code"] = API::OtherFailed;
|
||||
const_cast<Value &>(val)["msg"] = ex.what();
|
||||
}else{
|
||||
} else {
|
||||
const_cast<Value &>(val)["data"]["key"] = key;
|
||||
}
|
||||
invoker("200 OK", headerOut, val.toStyledString());
|
||||
@ -1234,6 +1240,8 @@ void installWebApi() {
|
||||
addFFmpegSource("http://hls-ott-zhibo.wasu.tv/live/272/index.m3u8",/** ffmpeg拉流支持任意编码格式任意协议 **/
|
||||
dst_url,
|
||||
(1000 * timeout_sec) - 500,
|
||||
false,
|
||||
false,
|
||||
[invoker,val,headerOut](const SockException &ex,const string &key){
|
||||
if(ex){
|
||||
const_cast<Value &>(val)["code"] = API::OtherFailed;
|
||||
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <inttypes.h>
|
||||
#include <cinttypes>
|
||||
#include "HlsParser.h"
|
||||
#include "Util/util.h"
|
||||
#include "Common/Parser.h"
|
||||
|
@ -223,6 +223,7 @@ void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t d
|
||||
}
|
||||
#else
|
||||
void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,int bytes) {}
|
||||
void DecoderImp::onStream(int stream,int codecid,const void *extra,int bytes,int finish) {}
|
||||
#endif
|
||||
|
||||
void DecoderImp::onTrack(const Track::Ptr &track) {
|
||||
|
@ -57,9 +57,10 @@ void RtpSession::onManager() {
|
||||
}
|
||||
|
||||
void RtpSession::onRtpPacket(const char *data, uint64_t len) {
|
||||
if (len > 1024 * 4) {
|
||||
throw SockException(Err_shutdown, "rtp包长度异常,发送端可能缓存溢出并覆盖");
|
||||
if (len > 1024 * 10) {
|
||||
throw SockException(Err_shutdown, StrPrinter << "rtp包长度异常(" << len << "),发送端可能缓存溢出并覆盖");
|
||||
}
|
||||
|
||||
if (!_process) {
|
||||
uint32_t ssrc;
|
||||
if (!RtpSelector::getSSRC(data, len, ssrc)) {
|
||||
|
@ -113,7 +113,7 @@ bool RtpReceiver::handleOneRtp(int track_index, TrackType type, int samplerate,
|
||||
}
|
||||
|
||||
if (rtp_raw_len <= rtp.offset) {
|
||||
WarnL << "无有效负载的rtp包:" << rtp_raw_len << " <= " << (int) rtp.offset;
|
||||
//无有效负载的rtp包
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,10 @@ RtspPlayer::~RtspPlayer(void) {
|
||||
}
|
||||
void RtspPlayer::teardown(){
|
||||
if (alive()) {
|
||||
sendRtspRequest("TEARDOWN" ,_content_base);
|
||||
shutdown(SockException(Err_shutdown,"teardown"));
|
||||
if (!_content_base.empty()) {
|
||||
sendRtspRequest("TEARDOWN", _content_base);
|
||||
}
|
||||
shutdown(SockException(Err_shutdown, "teardown"));
|
||||
}
|
||||
|
||||
_md5_nonce.clear();
|
||||
@ -232,7 +234,7 @@ void RtspPlayer::sendSetup(unsigned int track_idx) {
|
||||
}
|
||||
break;
|
||||
case Rtsp::RTP_MULTICAST: {
|
||||
sendRtspRequest("SETUP",baseUrl,{"Transport","Transport: RTP/AVP;multicast"});
|
||||
sendRtspRequest("SETUP",baseUrl,{"Transport","RTP/AVP;multicast"});
|
||||
}
|
||||
break;
|
||||
case Rtsp::RTP_UDP: {
|
||||
|
Loading…
Reference in New Issue
Block a user