失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 基于RTSP的流媒体播放器制作(2)

基于RTSP的流媒体播放器制作(2)

时间:2024-01-30 17:21:26

相关推荐

基于RTSP的流媒体播放器制作(2)

Section I Problem Specification

实验目的

本次实验室在MFC环境下使用socket制作的应用程序,实现对RTSP与RTP协议的解析并播放缓存的媒体流。实现一边下载一边播放的音乐播放器。客户端使用RTSP协议与LIVE555服务器进行通信,如果与服务器的通信无误就启动RTP线程开始缓存文件并进行播放。本次程序设计还包括一些其他功能:

1使用MFC进行界面的设计

2使用RTP将收到文件下载到本地,进行播放

3 播放控制,包括暂停,播放,终止,快进,快退,拖动播放时间播放,音量控制,播放时间条随播放时间变化。

实验背景

1RTSP协议

RTSP(Real Time Streaming Protocol),实时流协议,是一种流媒体

控制协议。。RTSP是一个多媒体播放控制协议,默认使用554或8554端口,用来使用户在播放从因特网下载的实时数据时能够进行控制,即控制实时数据的传输。RTSP 仅仅是使媒体播放器能控制多媒体流的传送。也就是说,RTSP只用于控制媒体流的传输。尽管有时可以把RTSP控制信息和媒体数据流交织在一起传送,但一般情况RTSP本身并不用于转送媒体流数据。媒体数据的传送可通过RTP/RTCP等协议来完成。

本实验中RTSP基于Socket连接,在建立Socket连接后,发送RTSP命令来

获取所请求的文件。RTP协议用来接收传来的文件数据。

RTSP协议有两种,一种是请求消息(request),一是回应消息(response),两种消息的格式不同。

请求格式 响应格式

其中URL是请求的地址,有两种:

一般是rtsp://192.168.0.1:(你的服务器的地址)/视频流的名字

如果地址有域名类似格式rtsp://computing./Angel.mp3

首部行用来加入交互命令,如下是简易的交互过程。

交互详细信息:

OPTION, 目的是得到服务器提供的可用方法

请求:

OPTIONSrtsp://computing./Angel.mp3 RTSP/1.0

CSeq: 1 //每个消息都有序号来标记,第一个包通常是option请求消息

User-Agent: VLC media player (LIVE555 Streaming Mediav.01.05)

响应:

RTSP/1.0 200 OK

Server: UServer 0.9.7_rc1

Cseq: 1 //每个回应消息的cseq数值和请求消息的cseq相对应

Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE,SCALE,

GET_PARAMETER //服务器提供的可用的方法

DESCRIBE,为了得到会话描述信息(SDP)

请求:

DESCRIBE rtsp://computing./Angel.mp3RTSP/1.0

CSeq: 2

Accept: application/sdp

User-Agent: VLCmedia player (LIVE555 Streaming Media v.01.05)

响应:

RTSP/1.0 200 OK

Cseq: 2

Content-Length: 367

Content-Type: application/sdp

//以下都是sdp信息

a=range:npt=0-

SETUP,客户端提醒服务器建立会话,并确定传输模式

请求:

SETUP rtsp://computing./Angel.mp3/trackID=0RTSP/1.0

CSeq: 3

Transport:RTP/AVP/TCP;unicast;interleaved=0-1

User-Agent: VLCmedia player (LIVE555 Streaming Media v.01.05)

响应:

RTSP/1.0 200 OK

Server: UServer 0.9.7_rc1

Cseq: 3

Session: 6310936469860791894 //服务器回应的会话标识符

Cache-Control: no-cache

Transport: RTP/AVP/TCP;unicast;interleaved=0-1;ssrc=6B8B4567

PLAY,客户端发送播放请求

请求:

PLAYrtsp://computing./Angel.mp3 RTSP/1.0

CSeq: 4

Session: 6310936469860791894

Range: npt=0.000- //设置播放时间的范围

User-Agent: VLC mediaplayer (LIVE555 Streaming Media v.01.05)

响应:

RTSP/1.0 200 OK

Server: UServer 0.9.7_rc1

Cseq: 4

Session: 6310936469860791894

Range: npt=0.000000-

RTP-Info: url=trackID=0;seq=17040;rtptime=1467265309

TEARDOWN,客户端发起关闭请求

请求:

TEARDOWN rtsp://computing./Angel.mp3RTSP/1.0

CSeq: 5

Session: 6310936469860791894

User-Agent: VLCmedia player (LIVE555 Streaming Media v.01.05)

响应:

RTSP/1.0 200 OK

Server: UServer 0.9.7_rc1

Cseq: 5

Session: 6310936469860791894

Connection: Close

本实验中,RTP使用了jrtplib插件来接收数据。JRTPLIB 是一个用C++语言实现的RTP库,包括UDP通讯

2VLC

VLC多媒体播放器(最初命名为VideoLAN客户端)是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影音光盘及各类流式协议。它也能作为unicast或 multicast的流式服务器在IPv4或 IPv6的高速网络连接下使用。它融合了FFmpeg计划的解码器与libdvdcss程序库使其有播放多媒体文件及加密DVD影碟的功能。

本实验中通过VLC的函数来播放音乐,并控制音乐的一些基本操作。

vlc一些基本方法:

libvlc_new():创建libvlc_instance_t。

libvlc_media_new_path()://通过文件路径创建一个媒体实例

libvlc_media_player_new_from_media()://创建VLC媒体播放器

libvlc_media_player_release():释放libvlc_media_player_t

libvlc_media_release():释放libvlc_media_t。

libvlc_release():释放libvlc_instance_t

libvlc_media_player_play():播放。

libvlc_media_player_pause():暂停。

libvlc_media_player_stop():停止。

Section II Solution Method and Design

本项目用到的开发平台和程序库主要有:

l Operating System: Microsoft Windows

l Programming Language: C++

l Development Platform: Microsoft Visual Studio

winsock2

本次实验主要流程:

建立Socket连接->启动RTSP线程->启动RTP线程->启动播放线程->释放资源

建立Socket:

启动RTSP线程:

p->rtsp = RTSP(p->rtspURI.getURI(),&socket); // 创建RTSP报文类实例

//向服务器发送rtsp请求

p->rtsp.sendOption();

p->rtsp.recvOption();

p->rtsp.sendDescribe();

p->rtsp.recvDescribe();

p->rtsp.sendSetup(RTPPORT);

p->rtsp.recvSetup();

p->rtsp.sendPlay();

p->rtsp.recvPlay();

//开启RTP线程

Sleep(1000);

AfxBeginThread(RtpThread,p, THREAD_PRIORITY_NORMAL, 0, 0, NULL);

//RTSP不响应会断开

while (true)

{

Sleep(10000); // 每隔10秒钟,对线路进行一次保活操作

if(p->download) // 如果播放器还在下载

{

p->rtsp.sendParameter(); // 保活线路

p->rtsp.recvParameter();

}

else

{

p->MessageBox("文件传输完成!");

break;

}

}

RTP线程:

int length = socket.RecvUdp(data, sizeof(data)); // 利用UDP协议接收传输的数据

启动播放线程:

vlc =libvlc_new(vlc_argc, vlc_args);

media =libvlc_media_new_path(vlc, pMediaPathName); //通过文件路径创建一个媒体实例

player =libvlc_media_player_new_from_media(media); //创建VLC媒体播放器

libvlc_media_parse(media); //解析媒体实例

libvlc_media_player_set_media(player,media);

libvlc_media_player_play(player);

程序类图:

BlockSocket控制Socket连接方法

RTSP发送rtsp消息

URI用来解析输入的url地址,检测文件名正确性,获取文件名,端口

VlcCtrl控制播放媒体实例

CRTSPClientMFC控制主线程

Section III Test Cases and Results Analysis

两个版本,一个Win32控制台程序,一个MFC程序

Win32控制台程序:

1.启动程序输入连接的地址,输错会打印错误信息,正确则利用socket获取主机地址,并打印出来,

然后自动开启RTSP线程和RTP线程,等待几秒后,开始播放

播放过程中,按程序提醒可以测试音量功能,播放暂停功能,快进快退功能。

MFC程序:

1.程序主界面

程序开始,没有下载直接点播放按钮,会弹出如下错误

输入地址错误,则弹出格式错误。

Section IV Conclusion

问题:

Win32控制台中:

1、 使用strcmp("rtsp://",this->uri.substr(0,7).c_str())作比较时,开始没有加上c_str()则报错,原因是基本的string类不能和char*比较,而c_str()作用是c_str() 以 char* 形式传回 string内含字符串。

2、 字符串相加不能存在int型,需要转换,string option = "OPTIONS" + uri.getURI() +" RTSP/1.0\r\nCSeq: " + CSeq + "\r\n" + userAgent+"\r\n";

使用itoa函数char *itoa( int value, char *string,intradix); value:欲转换的数据。 string:目标字符串的地址。radix:转换后的进制数,可以是10进制、16进制等。atoi是把字符串转换成int型。

3、 开始写RTSP请求时,末尾只写了一个“\r\n”,结果收不到包,解决办法应该是写”\r\n\r\n”。

4、 环境配置出错,运行后出现mainlibvlc error:no plugins found !check your vlc installation错误,解决办法把libvlc.dll, libvlccore.lib和plugins文件放在DEBUG目录下。

5、 播放音乐时不出声音,由于RTP还没有获取传输文件,就开始播放,解决办法是在开启播放线程时先等几秒,然后再播放。

MFC中问题:

1、 上面的第五个问题,在MFC中Sleep几秒钟会延迟,主要表示是下面的列表信息等了几秒才显示,然后发现不用Sleep也能正常播放,说明在MFC中线程的处理比win32快。

2、 由于使用线程的时候没有用信号量控制,导致在写播放线程后,一些例如快进,播放等操作会比线程执行的更快,产生内存泄露,用了一个变量控制,写的不是很好。

3、 调节音量的地方有两个问题,一个是静态文本控件如何改变数值,一个就是使用滑动条拖动时libvlc_audio_set_volume(player, volume)报错,询问了一些人遇到了这个问题,可能是因为程序开始会执行这个函数,所以出错,加变量控制把第一次执行跳过就好了。

未解决问题:

由于时间和能力有限,程序还有一些未解决的问题。

播放时间拖动条的功能只实现了随播放时间变化,拖动到指定地方进行播放功能没有实现。

RTP在传数据时有时会有错误,出现杂音,Win32版本中出现的error就是这个原因

下载速度如果没有播放速度快,播放就会停止,没有继续缓存

写线程没有用事件控制,后期调试时,使用了很多变量控制,对程序的可读性和封装造成了一定影响。

Section VI Appendix

下面列出了实现系统功能的关键代码段。

1.URI地址分析

/*一般是rtsp://192.168.0.1:(你的服务器的地址)/视频流的名字

如果地址有域名类似格式rtsp://computing./Angel.mp3

采用默认的端口

*/

2. //判断地址是否正确

3. bool URI::uriIsCorrect()

4. {

5. //先检查头部

6. if(strcmp("rtsp://",uri.substr(0,7).c_str())!=0){

7. return false;

8. }

9. else

10. {

11. if(strcmp("",this->getFilename().c_str())!=0)

12. {

13. return true;

14. }

15. else

16. return false;

17. }

18. }

19.

20. //获取主机地址

21. string URI::getHostname()

22. {

23. int startPos = strlen("rstp://");

24. int tempPos = uri.find(":",startPos);

25. if(tempPos == string::npos)

26. {

27. tempPos= uri.find("/",startPos);

28. }

29. stringm_hostname = uri.substr(startPos,tempPos-startPos);

30. if (isalpha(m_hostname[0]))

31. {

32. //使用gethostname获取主机名

33. WSADATAwsaData;

34. if (WSAStartup(MAKEWORD(2,2), &wsaData)!= 0)

35. {

36. cout<< "WSAStartup failed"<< endl;

37. return NULL;

38. }

39. hostent*remoteHost = gethostbyname(m_hostname.c_str());

40. if (remoteHost != NULL)

41. {

42. int i = 0;

43. in_addraddr;

44. while (remoteHost->h_addr_list[i] != 0)

45. {

46. addr.S_un.S_addr= *(u_long *)remoteHost->h_addr_list[i++];

47. return inet_ntoa(addr);

48. }

49. }

50. WSACleanup();

51. return NULL;

52. }

53. return m_hostname;

54. }

55.

56. //获取端口号

57. string URI::getPort()

58. {

59. int startPos = strlen("rtsp://");

60. int tempPos = uri.find(":",startPos);

61. if(tempPos == string::npos)

62. {

63. return "554";

64. }

65. else

66. {

67. int endPos = uri.find("/",startPos);

68. return uri.substr(tempPos,endPos-tempPos);

69. }

70. }

71.

72. //获取文件名

73. string URI::getFilename()

74. {

75. int startPos=strlen("rtsp://");

76. int tempPos = uri.find("/",startPos);

77.

78. if(tempPos == string::npos) //如果没有找到

79. {

80. return "";

81. }

82. else //返回文件名

83. {

84. int endPos = uri.length()-1;

85. return uri.substr(tempPos+1,endPos-tempPos);

86. }

87. }

88.RTSP线程

89. RTSP::RTSP(string uri,BlockSocket *blockSocket)

90. {

91. this->uri = URI(uri);

92. this->blockSocket = blockSocket;

93. CSeq = 0;

94. userAgent ="User-Agent: VLC media player (LIVE555Streaming Media v.01.05)";

95. m_totalTime= 0;

96.

97. }

98.

99. int RTSP::getTotalTime()

100. {

101. return this->m_totalTime;

102. }

103.

104.

105. int RTSP::sendOption()//OPTION请求

106. {

107. CSeq++;

108. char c[5];

109. itoa(CSeq,c,10);

110. stringoption = "OPTIONS " + uri.getURI()+" RTSP/1.0\r\nCSeq: " + c + "\r\n" + userAgent + "\r\n\r\n";

111. if(blockSocket->Send((char*)option.c_str(),option.length()))

112. {

113. cout<<"OPTIONS发送失败!"<<endl;

114. return 1;

115. }

116. return 0;

117. }

118. char *RTSP::recvOption()

119. {

120. memset(data,'\0',sizeof(data));

121. if(blockSocket->Recv(data,sizeof(data)))

122. {

123. cout<<"OPSTIONS接受失败!"<<endl;

124. return "";

125. }

126. return data;

127. }

128. int RTSP::sendDescribe()//DESCRIBE请求

129. {

130. CSeq++;

131. char c[5];

132. itoa(CSeq,c,10);

133. stringdescribe = "DESCRIBE " +uri.getURI() +" RTSP/1.0\r\nCSeq: "+ c + "\r\nAccept: application/sdp\r\n"+ userAgent + "\r\n\r\n";

134. if(blockSocket->Send((char*)describe.c_str(),describe.length()))

135. {

136. cout<<"DESCRIBE发送失败!"<<endl;

137. return 1;

138. }

139.

140. return 0;

141. }

142. char *RTSP::recvDescribe()

143. {

144. memset(data,'\0',sizeof(data));

145. if(blockSocket->Recv(data,sizeof(data)))

146. {

147. cout<<"DESCRIBE接受失败!"<<endl;

148. return "";

149. }

150. //发现文件时间长度

151. stringtimes(data);

152. int startPos = times.find("a=range:npt=0-")+14;

153. int endPos = times.find("\r\n",startPos);

154. stringm_time = times.substr(startPos,endPos-startPos);

155. this->m_totalTime = atoi(m_time.c_str())*1000;

156. //cout<<m_time<<endl;

157. return data;

158. }

159. int RTSP::sendSetup(char*port)//SETUP请求

160. {

161. CSeq++;

162. char c[5];

163. itoa(CSeq,c,10);

164. int port1 = atoi(port)+1;//指定RTP端口号

165. char mport[6];

166. itoa(port1,mport, 10);

167. stringsetup = "SETUP " + uri.getURI() +" RTSP/1.0\r\nCSeq: " + c + "\r\n" + userAgent + "\r\nTransport: RTP/AVP;unicast;client_port="+ port +"-"+ mport +"\r\n\r\n";

168. if(blockSocket->Send((char*)setup.c_str(),setup.length()))

169. {

170. cout<<"SETUP发送失败!"<<endl;

171. return 1;

172. }

173. return 0;

174. }

175. char *RTSP::recvSetup()

176. {

177. memset(data,'\0',sizeof(data));

178. if(blockSocket->Recv(data,sizeof(data)))

179. {

180. cout<<"SETUP接受失败!"<<endl;

181. return "";

182. }

183. stringsetupData(data);

184. int startPos = setupData.find("Session: ")+9;//还有一个空格

185. int temp=0;

186. while(data[startPos+temp]!=''&& data[startPos+temp]!='\r')

187. {

188. temp++;

189. }

190. char m_session[100];

191. memset(m_session,'\0', 100);

192. memcpy(m_session,data+startPos, temp);

193. this->session = m_session;

194. return data;

195. }

196. int RTSP::sendPlay()//PLAY请求

197. {

198. CSeq++;

199. char c[5];

200. itoa(CSeq,c,10);

201. stringplay = "PLAY " + uri.getURI() +" RTSP/1.0\r\nCSeq: " + c +"\r\n"+ userAgent+"\r\nSession: "+ this->session +"\r\nRange:npt=0.000-\r\n" +"\r\n\r\n";

202. if(blockSocket->Send((char*)play.c_str(),play.length()))

203. {

204. cout<<"PLAY发送失败!"<<endl;

205. return 1;

206. }

207. return 0;

208. }

209. char *RTSP::recvPlay()

210. {

211. memset(data,'\0',sizeof(data));

212. if(blockSocket->Recv(data,sizeof(data)))

213. {

214. cout<<"PLAY接受失败!"<<endl;

215. return "";

216. }

217. return data;

218. }

219.

220. int RTSP::sendPause()

221. {

222. CSeq++;

223. char c[5];

224. itoa(CSeq,c,10);

225. string pause= "PAUSE " + uri.getURI() +" RTSP/1.0\r\nCSeq: " + c + "\r\nSession: "+ this->session +"\r\n"+userAgent +"\r\n\r\n";

226. if(blockSocket->Send((char*)pause.c_str(),pause.length()))

227. {

228. cout<<"PAUSE发送失败!"<<endl;

229. return 1;

230. }

231. return 0;

232. }

233. char *RTSP::recvPause()

234. {

235. memset(data,'\0',sizeof(data));

236. if(blockSocket->Recv(data,sizeof(data)))

237. {

238. cout<<"PAUSE接受失败!"<<endl;

239. return "";

240. }

241. return data;

242. }

243. int RTSP::sendTeardown()

244. {

245. CSeq++;

246. char c[5];

247. itoa(CSeq,c,10);

248. stringteardown = "TEARDOWN " + uri.getURI()+" RTSP/1.0\r\nCSeq: " + c + "\r\nSession: "+ this->session +"\r\n"+userAgent +"\r\n\r\n";

249. if(blockSocket->Send((char*)teardown.c_str(),teardown.length()))

250. {

251. cout<<"TEARDOWN发送失败!"<<endl;

252. return 1;

253. }

254. return 0;

255. }

256. char *RTSP::recvTeardown()

257. {

258. memset(data,'\0',sizeof(data));

259. if(blockSocket->Recv(data,sizeof(data)))

260. {

261. cout<<"TEARDOWN接受失败!"<<endl;

262. return "";

263. }

264. return data;

265. }

266. int RTSP::sendParameter()

267. {

268. CSeq++;

269. char c[5];

270. itoa(CSeq,c,10);

271. stringparameter = "GET_PARAMETER " + uri.getURI()+" RTSP/1.0\r\nCSeq: " + c + "\r\nSession: "+ this->session +"\r\n"+userAgent +"\r\n\r\n";

272. if(blockSocket->Send((char*)parameter.c_str(),parameter.length()))

273. {

274. cout<<"GET_PARAMETER发送失败!"<<endl;

275. return 1;

276. }

277. return 0;

278. }

279. char *RTSP::recvParameter()

280. {

281. memset(data,'\0',sizeof(data));

282. if(blockSocket->Recv(data,sizeof(data)))

283. {

284. cout<<"GET_PARAMETER接受失败!"<<endl;

285. return "";

286. }

287. return data;

288. }

RTSP控制代码

UINTCRTSPClientMFCDlg::RtspThread(PVOID lpParam)

{

CRTSPClientMFCDlg *p = (CRTSPClientMFCDlg*)lpParam;

BlockSocket socket = BlockSocket();

if(socket.Initialize())

{

p->MessageBox("SOCKET打开失败!");

return0;

}

if(socket.HintsAndResult(p->rtspURI.getHostname().c_str(),p->rtspURI.getPort().c_str()))

{

p->MessageBox("获取地址失败!");

return0;

}

if(socket.Open())

{

p->MessageBox("SCOKET创建失败!");

return0;

}

if(socket.Connect())

{

p->MessageBox("SOCKET连接失败!");

return0;

}

p->rtsp = RTSP(p->rtspURI.getURI(),&socket); //创建RTSP报文实例

//向服务器发送RTSP请求

p->rtsp.sendOption();

p->rtsp.recvOption();

p->rtsp.sendDescribe();

p->rtsp.recvDescribe();

p->rtsp.sendSetup(RTPPORT);

p->rtsp.recvSetup();

p->rtsp.sendPlay();

p->rtsp.recvPlay();

p->hasRTSP = true;

//时间赋值

p->totalTime = p->rtsp.getTotalTime();

CString m_time;

m_time.Format("[00:00:00/%02d:%02d:%02d]",p->totalTime/3600000,p->totalTime/60000,(p->totalTime/1000-(p->totalTime/60000*60)));

p->strTime->SetWindowText(m_time);

//开启RTP线程

Sleep(1000);

p->m_listInfo.InsertItem(p->infoCount++,"RTSP请求成功开始传输数据...");

p->m_listInfo.InsertItem(p->infoCount++,"---------------------------------");

AfxBeginThread(RtpThread, p,THREAD_PRIORITY_NORMAL, 0, 0, NULL);

//RTSP不响应会断开

while (true)

{

Sleep(10000); // 每隔10秒激活一次

if(p->download) // 如果播放器还在下载

{

p->rtsp.sendParameter(); // 保活线路

p->rtsp.recvParameter();

}

else

{

p->MessageBox("文件传输完成");

break;

}

}

p->rtsp.sendTeardown();

p->rtsp.recvTeardown();

socket.Close();

socket.Cleanup();

return 0;

}

RTP控制线程:

UINTCRTSPClientMFCDlg::RtpThread(PVOID lpParam)// RTP线程

{

CRTSPClientMFCDlg *p = (CRTSPClientMFCDlg*)lpParam;

BlockSocket socket = BlockSocket();

if(socket.Initialize())

{

p->MessageBox("SOCKET打开连接失败!");

return0;

}

if(socket.BindUdp(RTPPORT))

{

p->MessageBox("绑定UDP失败!");

return0;

}

//传输文件

fstream file; // 创建文件流

file.open(p->rtspURI.getFilename(),ios::out|ios::binary|ios::trunc);// 打开文件流

chardata[MAX_BUFF_SIZE];

memset(data, '\0',sizeof(data));

// GetLocalTime(&timesend);

int length =socket.RecvUdp(data,sizeof(data)); // 利用UDP接收传输数据

// cout<<timesend.wHour<<":"<<timesend.wMinute<<":"<<timesend.wSecond<<":"<<timesend.wMilliseconds<<endl;

int sum = 0;

file.write(data+433, length-433); //第一次接收会有多余东西

sum += length - 433;

while (true)

{

memset(data, '\0',sizeof(data));

length = socket.RecvUdp(data, sizeof(data));

if(length <= 0)

{

p->download = false;

break;

}

else

{

file.write(data+16, length-16);

sum += length - 16;

}

}

return 0;

}

VLC控制代码:

void VlcCtrl::init()

{

int vlc_argc= 0;

char*vlc_args[100];

vlc_args[vlc_argc++] = "--ignore-config";

vlc = libvlc_new(vlc_argc, vlc_args);

}

void VlcCtrl::openMedia(constchar* pMediaPathName)

{

media = libvlc_media_new_path(vlc,pMediaPathName); //创建一个媒体实例

player = libvlc_media_player_new_from_media(media); //创建vlc播放器

libvlc_media_parse(media); //解析媒体实例

libvlc_media_player_set_media(player,media);

}

void VlcCtrl::pause()

{

if(player)

{

libvlc_media_player_pause (player);

}

}

void VlcCtrl::play()

{

if(player)

{

libvlc_media_player_play (player);

}

}

bool VlcCtrl::IsPlaying()

{

if (player)

{

return(1 == libvlc_media_player_is_playing(player));

}

return false;

}

void VlcCtrl::stop()

{

if(player)

{

libvlc_media_player_stop (player);

}

}

int64_tVlcCtrl::GetLength()

{

int64_t length =libvlc_media_player_get_length(player);

returnlength;

}

void VlcCtrl::FastForward()

{

if (player)

{

libvlc_time_t time =libvlc_media_player_get_time(player) + 5000;

int64_t allTime = GetLength();

if(time > allTime)

{

time = allTime;

}

libvlc_media_player_set_time(player,time);

}

}

void VlcCtrl::BackBackward()

{

if (player)

{

libvlc_time_t time = libvlc_media_player_get_time(player)- 5000;

int64_t allTime = GetLength();

if(time < 0)

{

time = 0;

}

libvlc_media_player_set_time(player,time);

}

}

void VlcCtrl::SetVolume(intvolume)

{

libvlc_audio_set_volume(player, volume);

}

bool VlcCtrl::hasPlayer()

{

if(player)

return true;

else

return false;

}

int64_tVlcCtrl::GetTime()

{

int64_t time =libvlc_media_player_get_time(player);

returntime;

}

Play控制线程:

UINTCRTSPClientMFCDlg::PlayThread(PVOID lpParam)// PLAY线程

{

CRTSPClientMFCDlg *p = (CRTSPClientMFCDlg*)lpParam;

p->vlcCtrl.init();

p->vlcCtrl.openMedia(p->rtspURI.getFilename().data());

p->hasPlayer = true;

p->vlcCtrl.play();

while(1)

{

p->UpdatePosition();

Sleep(1000);

}

return 0;

}

如果觉得《基于RTSP的流媒体播放器制作(2)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。