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

Section I Problem Specification

实验目的

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

1使用MFC进行界面的设计

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

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

 

实验背景

1  RTSP协议

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

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

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

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

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

            请求格式                             响应格式

基于RTSP的流媒体播放器制作(2)_第1张图片

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

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

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

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


交互详细信息:

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

    请求:

    OPTIONSrtsp://computing.cuc.edu.cn/Angel.mp3 RTSP/1.0

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

User-Agent: VLC media player (LIVE555 Streaming Mediav2016.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.cuc.edu.cn/Angel.mp3RTSP/1.0

CSeq: 2

Accept: application/sdp

User-Agent: VLCmedia player (LIVE555 Streaming Media v2016.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.cuc.edu.cn/Angel.mp3/trackID=0RTSP/1.0

CSeq: 3

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

User-Agent: VLCmedia player (LIVE555 Streaming Media v2016.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.cuc.edu.cn/Angel.mp3 RTSP/1.0

CSeq: 4

Session: 6310936469860791894

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

User-Agent: VLC mediaplayer (LIVE555 Streaming Media v2016.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.cuc.edu.cn/Angel.mp3RTSP/1.0

CSeq: 5

Session: 6310936469860791894

User-Agent: VLCmedia player (LIVE555 Streaming Media v2016.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通讯

 

 

2   VLC

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 2010

 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协议接收传输的数据

启动播放线程:

基于RTSP的流媒体播放器制作(2)_第2张图片

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);

 

程序类图:

基于RTSP的流媒体播放器制作(2)_第3张图片

BlockSocket控制Socket连接方法

RTSP发送rtsp消息

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

VlcCtrl控制播放媒体实例

CRTSPClientMFC控制主线程


Section III Test Cases and Results Analysis

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

Win32控制台程序:

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

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

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


MFC程序:

1. 程序主界面


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

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

停止键从头来播放,时间滚动条随播放时间增加,开始音量没有设置为0,拖动音量才有效果

 

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.cuc.edu.cn/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 v2016.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;

}


你可能感兴趣的:(通信,计算机网络)