README.md 8.5 KB
Newer Older
xiongziliang committed
1
# 一个基于C++11简单易用的轻量级流媒体库
夏楚 committed
2 3 4
平台|编译状态
----|-------
Linux | [![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit)
夏楚 committed
5 6
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)
夏楚 committed
7
Android | [![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_android.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_android)
夏楚 committed
8
Windows | 已经完成移植
夏楚 committed
9

夏楚 committed
10
## 项目特点
xiongziliang committed
11 12 13
- 基于C++11开发,避免使用裸指针,代码稳定可靠;同时跨平台移植简单方便,代码清晰简洁。
- 打包多种流媒体协议(RTSP/RTMP/HLS),支持协议间的互相转换,提供一站式的服务。
- 使用epoll+线程池+异步网络IO模式开发,并发性能优越。
xiongziliang committed
14
- 只实现主流的的H264+AAC流媒体方案,代码精简,脉络清晰,适合学习。
xiongziliang committed
15

xiongziliang committed
16 17 18 19 20
## 功能清单
- RTSP
  - RTSP 服务器,支持RTMP/MP4转RTSP。
  - RTSP 播放器,支持RTSP代理。
  - 支持 `rtp over udp` `rtp over tcp` `rtp over http` `rtp组播`  四种RTP传输方式 。
xiongziliang committed
21

xiongziliang committed
22 23 24 25 26
- RTMP
  - RTMP 播放服务器,支持RTSP/MP4转RTMP。
  - RTMP 发布服务器,支持录制发布流。
  - RTMP 播放器,支持RTMP代理。
  - RTMP 推流客户端。
xiongziliang committed
27

xiongziliang committed
28
- HLS
xiongziliang committed
29
  - 支持HLS文件生成,自带HTTP文件服务器。
夏楚 committed
30 31 32 33
  
- HTTP[S]
  - 服务器支持`目录索引生成`,`文件下载`,`表单提交请求`
  - 客户端提供`文件下载器(支持断点续传)`,`接口请求器`
xiongziliang committed
34

xiongziliang committed
35
- 其他
xiongziliang committed
36 37 38
  - 支持输入YUV+PCM自动生成RTSP/RTMP/HLS/MP4.
  - 支持简单的telnet调试。
  - 支持H264的解析,支持B帧的POC计算排序。
xiongziliang committed
39 40 41
 
## 后续任务
- 提供更多的示例代码
xiongziliang committed
42

xiongziliang committed
43
## 编译(Linux)
xiongziliang committed
44 45
- 我的编译环境
  - Ubuntu16.04 64 bit + gcc5.4(最低gcc4.7)
夏楚 committed
46
  - cmake 3.5.1
夏楚 committed
47
- 编译
夏楚 committed
48
  
夏楚 committed
49 50
  ```
  cd ZLMediaKit
夏楚 committed
51
  ./build_for_linux.sh
夏楚 committed
52
  ```  
夏楚 committed
53
    
夏楚 committed
54 55 56 57 58 59
## 编译(macOS)
- 我的编译环境
  - macOS Sierra(10.12.1) + xcode8.3.1
  - Homebrew 1.1.3
  - cmake 3.8.0
- 编译
夏楚 committed
60
  
夏楚 committed
61 62 63 64 65 66 67
  ```
  cd ZLMediaKit
  ./build_for_mac.sh
  ```
	 
## 编译(iOS)
- 编译环境:`请参考macOS的编译指导。`
夏楚 committed
68 69 70 71
- 编译
  
  ```
  cd ZLMediaKit
夏楚 committed
72 73 74 75 76 77
  ./build_for_ios.sh
  ```
- 你也可以生成Xcode工程再编译:

  ```
  cd ZLMediaKit
夏楚 committed
78 79
  mkdir -p build
  cd build
夏楚 committed
80 81 82
  # 生成Xcode工程,工程文件在build目录下
  cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/iOS.cmake -DIOS_PLATFORM=SIMULATOR64 -G "Xcode"
  ```
夏楚 committed
83 84 85 86 87 88 89 90
  
## 编译(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)
- 编译
xiongziliang committed
91

夏楚 committed
92 93 94 95 96
  ```
  cd ZLMediaKit
  export ANDROID_NDK_ROOT=/path/to/ndk
  ./build_for_android.sh
  ```
夏楚 committed
97 98 99 100 101
## 编译(Windows)
- 我的编译环境
  - windows 10
  - visual studio 2017
  - [ZLToolKit](https://github.com/xiongziliang/ZLToolKit)
夏楚 committed
102
  - [字符转换工具](http://xz.mqego.com/soft1/gb2utf8.zip)
夏楚 committed
103
  - [cmake-gui](https://cmake.org/files/v3.10/cmake-3.10.0-rc1-win32-x86.msi)
夏楚 committed
104 105 106
  
- 编译
```
夏楚 committed
107 108
   1 请先编译安装ZLToolKit
   2 使用字符转换工具把代码(UTF8)转换成GBK(过滤器添加|*.cpp|*h|*.c)
夏楚 committed
109
   3 使用cmake-gui打开工程并生成vs工程文件(配置时可能需要指定ZLTookKit的路径).
夏楚 committed
110
   4 找到工程文件(ZLMediaKit.sln),双击用vs2017打开.
夏楚 committed
111 112 113 114
   5 选择编译Release 版本.
   6 依次编译 ZLMediaKit_static、ZLMediaKit_shared、ALL_BUILD、INSTALL.
   7 找到目标文件并运行测试用例.
   8 找到安装的头文件及库文件(在源码所在分区根目录).
夏楚 committed
115
```
夏楚 committed
116 117
## 使用方法
- 作为服务器:
夏楚 committed
118
	```
夏楚 committed
119 120 121
	TcpServer<RtspSession>::Ptr rtspSrv(new TcpServer<RtspSession>());
	TcpServer<RtmpSession>::Ptr rtmpSrv(new TcpServer<RtmpSession>());
	TcpServer<HttpSession>::Ptr httpSrv(new TcpServer<HttpSession>());
夏楚 committed
122
	TcpServer<HttpsSession>::Ptr httpsSrv(new TcpServer<HttpsSession>());
夏楚 committed
123 124 125 126
	
	rtspSrv->start(mINI::Instance()[Config::Rtsp::kPort]);
	rtmpSrv->start(mINI::Instance()[Config::Rtmp::kPort]);
	httpSrv->start(mINI::Instance()[Config::Http::kPort]);
夏楚 committed
127
	httpsSrv->start(mINI::Instance()[Config::Http::kSSLPort]);
夏楚 committed
128 129
	EventPoller::Instance().runLoop();
	```
夏楚 committed
130 131

- 作为播放器:
夏楚 committed
132 133
	```
	MediaPlayer::Ptr player(new MediaPlayer());
夏楚 committed
134 135 136 137 138 139
	player->setOnPlayResult([](const SockException &ex) {
		InfoL << "OnPlayResult:" << ex.what();
	});
	player->setOnShutdown([](const SockException &ex) {
		ErrorL << "OnShutdown:" << ex.what();
	});
夏楚 committed
140
	player->setOnVideoCB([&](const H264Frame &frame){
夏楚 committed
141 142
		//在这里解码H264并显示
	});
夏楚 committed
143
	player->setOnAudioCB([&](const AdtsFrame &frame){
夏楚 committed
144 145
		//在这里解码AAC并播放
	});
夏楚 committed
146
	//支持rtmp、rtsp
夏楚 committed
147 148
	(*player)[RtspPlayer::kRtpType] = PlayerBase::RTP_TCP;
	player->play("rtsp://admin:jzan123456@192.168.0.122/");
夏楚 committed
149
	EventPoller::Instance().runLoop();
夏楚 committed
150
	```
夏楚 committed
151
- 作为代理服务器:
夏楚 committed
152 153
	```
	//support rtmp and rtsp url
夏楚 committed
154 155 156
	//just support H264+AAC
	auto urlList = {"rtmp://live.hkstv.hk.lxdns.com/live/hks",
			"rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov"};
夏楚 committed
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
	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);
	}
夏楚 committed
173
	```
夏楚 committed
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
	
- 作为推流客户端器:
	```
	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();
	```
夏楚 committed
196 197
## QA
- 为什么VLC播放一段时间就停止了?
夏楚 committed
198 199
    
    由于ZLMediaKit在实现RTSP协议时,采用OPTIONS命令作为心跳包(在RTP over UDP时有效),如果播放器不持续发送OPTIONS指令,那么ZLMediaKit会断开连接。如果你要用第三方播放器测试,你可以改RTP over TCP方式或者修改ZLMediaKit的源码,修改位置位置为src/Rtsp/RtspSession.cpp RtspSession::onManager函数,修改成如下所示:
夏楚 committed
200
	```
夏楚 committed
201 202 203 204 205 206 207 208 209 210 211 212
  	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;
			}
		}
夏楚 committed
213
		/*if (m_rtpType != PlayerBase::RTP_TCP && m_ticker.elapsedTime() > 15 * 1000) {
夏楚 committed
214
			WarnL << "RTSP会话超时:" << getPeerIp();
夏楚 committed
215 216
			shutdown();
			return;
夏楚 committed
217 218
 		/*}
  	}
夏楚 committed
219
	```
夏楚 committed
220
- 怎么测试服务器性能?
夏楚 committed
221 222
    
    ZLMediaKit提供了测试性能的示例,代码在tests/test_benchmark.cpp。由于ZLToolKit默认关闭了tcp客户端多线程的支持,如果需要提高测试并发量,需要在编译ZLToolKit时启用ENABLE_ASNC_TCP_CLIENT宏,具体操作如下:
夏楚 committed
223 224 225 226
	```
	#编译ZLToolKit
	cd ZLToolKit
	mkdir -p build
夏楚 committed
227 228
	cd build 
	cmake .. -DENABLE_ASNC_TCP_CLIENT
夏楚 committed
229 230
	make -j4
	sudo make install
夏楚 committed
231
	```
夏楚 committed
232

夏楚 committed
233
- github下载太慢了,有其他下载方式吗?
夏楚 committed
234 235 236 237
    
    你可以在通过开源中国获取最新的代码,地址为:
 
    [ZLToolKit](http://git.oschina.net/xiahcu/ZLToolKit)
夏楚 committed
238
  
夏楚 committed
239
    [ZLMediaKit](http://git.oschina.net/xiahcu/ZLMediaKit)
夏楚 committed
240 241


xiongziliang committed
242
## 联系方式
夏楚 committed
243
- 邮箱:<771730766@qq.com>
xiongziliang committed
244
- QQ群:542509000
xiongziliang committed
245