2012年(1008)
分类:
2012-08-01 11:07:30
原文地址:QT实现媒体播放器 作者:luozhiyong131
媒体播放器设计文档
一、功能概述:
n 文件格式:一般视频文件( *.vai *.rmvb)
n 基本功能:播放、停止、快进、快退
n 网络功能:从服务端下载、上传视频文件
n 播放模式:直接加载本地视频播放,从播放列表播放视频
二、功能具体实现:
2.1文件加载:
加载文件按键被触发,槽函数调用QFileDialog::getOpenFileName获得文件名
mediaObject->setCurrentSource(Phonon::MediaSource(filename));
对播放列表发出信号,更新播放列表
2.2播放功能:
判断是否正在播放
a)如果没有播放调用play()函数进入播放,改变播放按钮状态显示为暂停
b)否则调用pause()暂停改变播放按钮状态显示
2.3快进、快退
调用seek(stime 5000) stime现在正在播放的时间,stime由定时器更新值
2.4停止
调用stop()、clear()函数停止播放并释放资源
刷新显示屏(先关、再显示)
ui->frameVideo->close();
ui->frameVideo->show();
2.5媒体库隐藏与显示
在主窗口构造函数中初始化媒体库但并不显示
当媒体库按钮按下调用媒体库显示函数show()
当按键再次按下关闭媒体库close()
2.6播放列表操作
播放列表操作采用数据库(QSqlTableModel)包括增、删、查
数据库初始化:在主程序中调用连接数据库函数,连接数据库并打开表
播放列表更新:加载文件时主窗口发出新增文件信号,这信号连接到数据库插入函数。
文件下载完成时也会发出新增信号
播放列表删除: removeRow(curRow); curRow所选中的行
播放列表Play:获得选中行的文件名 先获得选中行号currentIndex().row()
查询数据库id 为row的信息得到文件名
发出播放信号,主窗口播放文件
三、网络功能:
传输协议选用:TCP UPD FTP
分析:一个服务器发给多个客户端
传输数据比较多,文件比较大
以上综合考虑所以选用TCP。因为TCP协议的程序使用的是客户端/服务器模式。所以需要单独设计服务器
QTcpSocket类来编写客户端程序,使用QTcpServer类编写服务器端程序。在服务器端进行端口的监听,一旦发现客户端的连接请求,利用自动发出newConnection()信号,关联这个信号到自己的槽函数,进行数据的发送。而在客户端,一旦有数据到来就会发出readyRead()信号,我们可以关联此信号,进行数据的接收。
编程模型
TCP服务器
初始化套接字 绑定 监听 接受连接 阻塞直到客户连接到达 接收 发送 接收 关闭
TCP客户端
初始化套接字 连接 发送 接收 关闭
A) 服务器设计:
a) 服务器功能:发送与接收数据
b) 服务器初始化:建立套接字、监听端口tcpServer.listen(QHostAddress::LocalHost,6666),等待客户端连接请求。初始化套接字,监听本地主机的一个端口,这里使用6666,然后关联newConnection()信号与自己写的acceptConnection()槽函数。一旦有客户端的连接请求,就会执行acceptConnection()函数,connect(&tcpServer,SIGNAL(newConnection()),this, SLOT(acceptConnection()));
C) 服务器接受端客户端连接请求,使用tcpServer的nextPendingConnection()函数来获取已经建立的连接的Tcp套接字,使用它来完成数据的发送、接收、异常处理操作
void Widget::acceptConnection() //接受连接
{
tcpServerConnection = tcpServer.nextPendingConnection();
connect(tcpServerConnection,SIGNAL(readyRead()),
this, SLOT(updateServerProgress()));
connect(tcpServerConnection, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(tcpServerConnection,SIGNAL(bytesWritten(qint64)),
this, SLOT(updateClientProgress(qint64)));
ui->serverStatusLabel->setText(tr("接受连接"));
tcpServer.close();
}
数据收发:
A)服务端传给客户端:发送
1、获得要传输的文件: wfileName = QFileDialog::getOpenFileName(this);
2.调用发送函数:
为保证在客户端能接收到完整的文件,在数据流的最开始写入文件的大小、文件名等信息,这样客户端就可以根据大小信息来判断是否接受到了完整的文件。
发文件大概流程:
先进行文件头结构的发送,当发送成功时就服务器会发出bytesWritten(qint64)信号,这updateClientProgress(qint64 numBytes)函数中进行文件数据的传输和进度条的更新。这里使用了一个loadSize变量(始化为4*1024即4字节),它的作用是,将整个大的文件分成很多小的部分进行发送,每部分为4字节。而当连接出现问题时就会发出error(QAbstractSocket::SocketError)信号,这时就会执行displayError()函数。
B)服务端接收客户端文件
客户端有上传请求,服务端发出读信号
接收文件头结构头,获得文件的大小,文件名并创建文件;
接收数据、写入文件、更新进度条
接收数据完成
客户端收发数据与服务端基本类似(这里不再重复)
客户端手动下载资源
实现原理;
1、 客户端给服务器端发送下载请求
2、 服务端对下载请求作出回应,发送文件给客户端
3、 客户端接收数据
程序中的出现过的Bug
问题:客户端与服务端相互进行文件传送只能传一次,第二次传输有问题
解决:1、先解决服务端至客户端连续文件的传输
服务器端:发送文件完清空初始化控制传输条件的关键变量值
客户端:接收文件前初始化控制接收条件关键变量值
2、解决客户端至服务端连续文件的传输
客户端:发文件完初始化控制控制传输条件关键变量值
服务器端:接收文件完清空初始化控制接收条件的关键变量值