2017-04-22 21:45:58 +08:00
# 一个基于C++11简单易用的轻量级流媒体库
2017-05-03 00:00:15 +08:00
平台|编译状态
----|-------
Linux | [![Build Status ](https://travis-ci.org/xiongziliang/ZLMediaKit.svg?branch=master )](https://travis-ci.org/xiongziliang/ZLMediaKit)
2017-05-11 23:20:31 +08:00
macOS | [![Build Status ](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_mac.svg?branch=master )](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_mac)
iOS | [![Build Status ](https://travis-ci.org/xiongziliang/ZLMediaKit-build_for_ios.svg?branch=master )](https://travis-ci.org/xiongziliang/ZLMediaKit-build_for_ios)
2017-06-03 11:14:27 +08:00
Android | [![Build Status ](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_android.svg?branch=master )](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_android)
2017-08-10 16:56:13 +08:00
Windows | 已经完成移植
2017-05-03 00:00:15 +08:00
2017-05-06 00:07:32 +08:00
## 项目特点
2017-04-22 21:45:58 +08:00
- 基于C++11开发, 避免使用裸指针, 代码稳定可靠; 同时跨平台移植简单方便, 代码清晰简洁。
- 打包多种流媒体协议(RTSP/RTMP/HLS) , 支持协议间的互相转换, 提供一站式的服务。
- 使用epoll+线程池+异步网络IO模式开发, 并发性能优越。
2017-04-22 21:47:03 +08:00
- 只实现主流的的H264+AAC流媒体方案, 代码精简,脉络清晰,适合学习。
2017-04-01 16:42:00 +08:00
2017-04-22 21:45:58 +08:00
## 功能清单
- RTSP
- RTSP 服务器, 支持RTMP/MP4转RTSP。
- RTSP 播放器, 支持RTSP代理。
- 支持 `rtp over udp` `rtp over tcp` `rtp over http` `rtp组播` 四种RTP传输方式 。
2017-04-01 16:42:00 +08:00
2017-04-22 21:45:58 +08:00
- RTMP
- RTMP 播放服务器, 支持RTSP/MP4转RTMP。
- RTMP 发布服务器,支持录制发布流。
- RTMP 播放器, 支持RTMP代理。
- RTMP 推流客户端。
2017-04-01 16:42:00 +08:00
2017-04-22 21:45:58 +08:00
- HLS
2017-04-22 21:48:02 +08:00
- 支持HLS文件生成, 自带HTTP文件服务器。
2017-05-06 00:07:32 +08:00
- HTTP[S]
- 服务器支持`目录索引生成`,`文件下载`,`表单提交请求`。
- 客户端提供`文件下载器(支持断点续传)`,`接口请求器`。
2017-04-01 16:42:00 +08:00
2017-04-22 21:45:58 +08:00
- 其他
2017-04-22 21:48:02 +08:00
- 支持输入YUV+PCM自动生成RTSP/RTMP/HLS/MP4.
- 支持简单的telnet调试。
- 支持H264的解析, 支持B帧的POC计算排序。
2017-04-22 21:45:58 +08:00
## 后续任务
- 提供更多的示例代码
2017-04-01 16:42:00 +08:00
2017-04-22 22:57:43 +08:00
## 编译(Linux)
2017-04-22 21:45:58 +08:00
- 我的编译环境
- Ubuntu16.04 64 bit + gcc5.4(最低gcc4.7)
2017-05-03 00:00:15 +08:00
- cmake 3.5.1
2017-05-11 23:20:31 +08:00
- 编译
2017-05-03 00:16:53 +08:00
2017-05-11 23:20:31 +08:00
```
cd ZLMediaKit
2017-05-16 17:08:15 +08:00
./build_for_linux.sh
2017-05-11 23:20:31 +08:00
```
2017-05-03 00:00:15 +08:00
2017-05-11 23:20:31 +08:00
## 编译(macOS)
- 我的编译环境
- macOS Sierra(10.12.1) + xcode8.3.1
- Homebrew 1.1.3
- cmake 3.8.0
- 编译
2017-05-03 00:16:53 +08:00
2017-05-11 23:20:31 +08:00
```
cd ZLMediaKit
./build_for_mac.sh
```
## 编译(iOS)
- 编译环境:`请参考macOS的编译指导。`
2017-05-03 00:00:15 +08:00
- 编译
2017-05-11 23:20:31 +08:00
```
cd ZLMediaKit
./build_for_ios.sh
```
- 你也可以生成Xcode工程再编译:
2017-05-03 00:00:15 +08:00
```
cd ZLMediaKit
mkdir -p build
cd build
2017-05-11 23:20:31 +08:00
# 生成Xcode工程, 工程文件在build目录下
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/iOS.cmake -DIOS_PLATFORM=SIMULATOR64 -G "Xcode"
```
2017-06-03 11:14:27 +08:00
## 编译(Android)
- 我的编译环境
- macOS Sierra(10.12.1) + xcode8.3.1
- Homebrew 1.1.3
- cmake 3.8.0
- [android-ndk-r14b ](https://dl.google.com/android/repository/android-ndk-r14b-darwin-x86_64.zip )
- 编译
2017-04-22 21:45:58 +08:00
2017-06-03 11:14:27 +08:00
```
cd ZLMediaKit
export ANDROID_NDK_ROOT=/path/to/ndk
./build_for_android.sh
```
2017-08-10 16:56:13 +08:00
## 编译(Windows)
- 我的编译环境
- windows 10
- visual studio 2017
- [ZLToolKit ](https://github.com/xiongziliang/ZLToolKit )
2017-09-14 11:20:25 +08:00
- [字符转换工具 ](http://xz.mqego.com/soft1/gb2utf8.zip )
2017-08-10 16:56:13 +08:00
- 编译
```
2017-09-14 11:11:13 +08:00
1 请先编译安装ZLToolKit
2 使用字符转换工具把代码(UTF8)转换成GBK(过滤器添加|*.cpp|*h|*.c)
2017-09-14 11:08:43 +08:00
3 使用vs2017打开ZLMediaKit源码根目录文件夹,然后自动生成工程文件, 工程文件路径请查看cmake输出.
4 找到工程文件(ZLMediaKit.sln),双击用vs2017打开.
5 编译 ALL_BUILD 项目.
6 找到目标文件并运行测试用例.
2017-08-10 16:56:13 +08:00
```
2017-06-05 17:53:58 +08:00
## 使用方法
- 作为服务器:
2017-06-05 18:08:31 +08:00
```
2017-06-05 17:53:58 +08:00
TcpServer< RtspSession > ::Ptr rtspSrv(new TcpServer< RtspSession > ());
TcpServer< RtmpSession > ::Ptr rtmpSrv(new TcpServer< RtmpSession > ());
TcpServer< HttpSession > ::Ptr httpSrv(new TcpServer< HttpSession > ());
2017-06-05 18:10:17 +08:00
TcpServer< HttpsSession > ::Ptr httpsSrv(new TcpServer< HttpsSession > ());
2017-06-05 17:53:58 +08:00
rtspSrv->start(mINI::Instance()[Config::Rtsp::kPort]);
rtmpSrv->start(mINI::Instance()[Config::Rtmp::kPort]);
httpSrv->start(mINI::Instance()[Config::Http::kPort]);
2017-06-05 18:10:17 +08:00
httpsSrv->start(mINI::Instance()[Config::Http::kSSLPort]);
2017-06-05 18:08:31 +08:00
EventPoller::Instance().runLoop();
```
2017-06-05 17:53:58 +08:00
- 作为播放器:
2017-06-05 18:08:31 +08:00
```
MediaPlayer::Ptr player(new MediaPlayer());
2017-06-05 17:53:58 +08:00
player->setOnPlayResult([](const SockException & ex) {
InfoL < < "OnPlayResult:" < < ex.what ( ) ;
});
player->setOnShutdown([](const SockException & ex) {
ErrorL < < "OnShutdown:" < < ex.what ( ) ;
});
2017-06-05 18:09:30 +08:00
player->setOnVideoCB([& ](const H264Frame & frame){
2017-06-05 17:53:58 +08:00
//在这里解码H264并显示
});
2017-06-05 18:09:30 +08:00
player->setOnAudioCB([& ](const AdtsFrame & frame){
2017-06-05 17:53:58 +08:00
//在这里解码AAC并播放
});
2017-06-05 18:08:31 +08:00
//支持rtmp、rtsp
2017-08-15 12:03:10 +08:00
(*player)[RtspPlayer::kRtpType] = PlayerBase::RTP_TCP;
player->play("rtsp://admin:jzan123456@192.168.0.122/");
2017-06-05 17:53:58 +08:00
EventPoller::Instance().runLoop();
2017-06-05 18:08:31 +08:00
```
2017-06-05 17:53:58 +08:00
- 作为代理服务器:
2017-06-05 18:08:31 +08:00
```
//support rtmp and rtsp url
2017-06-05 17:53:58 +08:00
//just support H264+AAC
auto urlList = {"rtmp://live.hkstv.hk.lxdns.com/live/hks",
"rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov"};
2017-06-05 18:13:49 +08:00
map< string , PlayerProxy::Ptr > proxyMap;
int i=0;
for(auto url : urlList){
//PlayerProxy构造函数前两个参数分别为应用名( app) ,流id( streamId)
//比如说应用为live, 流id为0, 那么直播地址为:
//http://127.0.0.1/live/0/hls.m3u8
//rtsp://127.0.0.1/live/0
//rtmp://127.0.0.1/live/0
//录像地址为:
//http://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
//rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
//rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
PlayerProxy::Ptr player(new PlayerProxy("live",to_string(i++).data()));
player->play(url);
proxyMap.emplace(string(url),player);
}
2017-06-05 18:08:31 +08:00
```
2017-06-06 20:15:08 +08:00
- 作为推流客户端器:
```
PlayerProxy::Ptr player(new PlayerProxy("app","stream"));
//拉一个流, 生成一个RtmpMediaSource, 源的名称是"app/stream"
//你也可以以其他方式生成RtmpMediaSource, 比如说MP4文件( 请研读MediaReader代码)
player->play("rtmp://live.hkstv.hk.lxdns.com/live/hks");
RtmpPusher::Ptr pusher;
//监听RtmpMediaSource注册事件,在PlayerProxy播放成功后触发。
NoticeCenter::Instance().addListener(nullptr,Config::Broadcast::kBroadcastRtmpSrcRegisted,
[&pusher ](BroadcastRtmpSrcRegistedArgs ){
//媒体源"app/stream"已经注册, 这时方可新建一个RtmpPusher对象并绑定该媒体源
const_cast< RtmpPusher::Ptr & > (pusher).reset(new RtmpPusher(app,stream));
//推流地址,请改成你自己的服务器。
//这个范例地址( 也是基于mediakit) 是可用的, 但是带宽只有1mb, 访问可能很卡顿。
pusher->publish("rtmp://jizan.iok.la/live/test");
});
EventPoller::Instance().runLoop();
```
2017-06-05 18:00:34 +08:00
## QA
- 为什么VLC播放一段时间就停止了?
2017-06-05 18:03:27 +08:00
由于ZLMediaKit在实现RTSP协议时, 采用OPTIONS命令作为心跳包( 在RTP over UDP时有效) , 如果播放器不持续发送OPTIONS指令, 那么ZLMediaKit会断开连接。如果你要用第三方播放器测试, 你可以改RTP over TCP方式或者修改ZLMediaKit的源码, 修改位置位置为src/Rtsp/RtspSession.cpp RtspSession::onManager函数,修改成如下所示:
2017-06-05 18:08:31 +08:00
```
2017-06-05 18:03:27 +08:00
void RtspSession::onManager() {
if (m_ticker.createdTime() > 10 * 1000) {
if (m_strSession.size() == 0) {
WarnL < < "非法链接:" < < getPeerIp ( ) ;
shutdown();
return;
}
if (m_bListenPeerUdpPort) {
UDPServer::Instance().stopListenPeer(getPeerIp().data(), this);
m_bListenPeerUdpPort = false;
}
}
2017-06-05 18:13:49 +08:00
/*if (m_rtpType != PlayerBase::RTP_TCP & & m_ticker.elapsedTime() > 15 * 1000) {
2017-06-05 18:03:27 +08:00
WarnL < < "RTSP会话超时:" < < getPeerIp ( ) ;
2017-06-05 17:53:58 +08:00
shutdown();
return;
2017-06-05 18:03:27 +08:00
/*}
}
2017-06-05 18:08:31 +08:00
```
2017-06-05 18:00:34 +08:00
- 怎么测试服务器性能?
2017-06-05 18:03:27 +08:00
ZLMediaKit提供了测试性能的示例, 代码在tests/test_benchmark.cpp。由于ZLToolKit默认关闭了tcp客户端多线程的支持, 如果需要提高测试并发量, 需要在编译ZLToolKit时启用ENABLE_ASNC_TCP_CLIENT宏, 具体操作如下:
2017-06-05 18:08:31 +08:00
```
#编译ZLToolKit
cd ZLToolKit
mkdir -p build
2017-08-28 10:04:43 +08:00
cd build
cmake .. -DENABLE_ASNC_TCP_CLIENT
2017-06-05 18:09:30 +08:00
make -j4
sudo make install
2017-06-05 18:08:31 +08:00
```
2017-06-05 17:53:58 +08:00
2017-06-05 18:00:34 +08:00
- github下载太慢了, 有其他下载方式吗?
2017-06-05 18:03:27 +08:00
你可以在通过开源中国获取最新的代码,地址为:
[ZLToolKit ](http://git.oschina.net/xiahcu/ZLToolKit )
2017-06-03 11:14:27 +08:00
2017-06-05 18:03:27 +08:00
[ZLMediaKit ](http://git.oschina.net/xiahcu/ZLMediaKit )
2017-06-05 17:53:58 +08:00
2017-04-22 21:45:58 +08:00
## 联系方式
2017-05-03 00:00:15 +08:00
- 邮箱:< 771730766 @ qq . com >
2017-04-22 21:45:58 +08:00
- QQ群: 542509000
2017-04-22 22:52:29 +08:00