基于QT播放器的实现(一)Rgb、YUV格式(附带代码)
基于QT播放器的实现(一)Rgb、YUV格式
- 色度空间转换
- YUV转RGB的公式
- 对本地RGB32视频图像的播放
色度空间转换
YUV颜色模型其实常用于视频传输和图像压缩。由于人类的眼睛,对亮度的敏感度远超过对色彩的敏感度,所以视频传输过程中,为了减小带宽,通常将色彩分量 UV的比例减小,以达到降低带宽的目的。这就出现了YUV4:4:4、YUV4:2:2、YUV4:1:1等格式。
RGB32使用32位来表示一个像素,RGB分量各用去8位,剩下的8位用作Alpha通道或者不用。(ARGB32就是带Alpha通道的RGB32。)注意在内存中RGB各分量的排列顺序为:BGRA BGRA BGRA…。通常可以使用RGB32数据结构来操作一个像素,它的定义为:
typedef struct RGB32 {
BYTE rgbBlue; // 蓝色分量
BYTE rgbGreen; // 绿色分量
BYTE rgbRed; // 红色分量
BYTE rgbReserved; // 保留字节(用作Alpha通道或忽略)
} RGB32;
YUV转RGB的公式
R = Y + 1.402 * (V-128)
G = Y - 0.34413 * (U-128) - 0.71414*(V-128)
B= Y + 1.772*(U-128)
对本地RGB32视频图像的播放
1、绘图显示函数 打开目录函数
void MainWindow ::paintEvent(QPaintEvent *)
{QPainter painter(this);painter.setBrush(Qt::black);QRect rect = ui->widget_video->geometry();painter.drawRect(rect);if (mImage.size().width() <= 0) return;//将图像按比例缩放成和窗口一样大小QImage img = mImage.scaled(ui->widget_video->size(),Qt::KeepAspectRatio);int x = ui->widget_video->width() - img.width();int y = ui->widget_video->height() - img.height();x /= 2;y /= 2;x += ui->widget_video->x();y += ui->widget_video->y();painter.drawImage(QPoint(x,y),img); //画出图像
}
/*接收信号函数传递来过的图像,并准备执行绘画函数*/
void MainWindow::slotGetOneFrame(QImage img)
{mImage = img;update(); //调用update将执行 paintEvent函数
}
/*打开目录按键的槽函数*/
void MainWindow::on_pushButton_open_clicked()
{QString s = QFileDialog::getOpenFileName(this, "", "视频绝对路径","rgb flie(*.rgb);;yuv file(*.yuv)");if (!s.isEmpty()){s.replace("/","\\");ui->lineEdit_filepath->setText(s);//将字符串写入lineEdit_filepath文本框}}
2、按开始播放的槽函数
void MainWindow::on_pushButton_display_clicked()
{/*提取三个文本框的内容*/QString filePath = ui->lineEdit_filepath->text();int width = ui->lineEdit_2_width->text().toInt();//toInt()表示将类型转化成intint height = ui->lineEdit_height->text().toInt();//视频播放帧数设置if(ui->fpsBox->currentIndex()==0)//如果下拉框中的数值是25fpsmThread->Setfps_25();else//否则mThread->Setfps_30();maxValue=filenumber();//滑动条最大值获取//设定滑条的范围,确保滑条的每一步为一帧ui->horizontalSlider->setRange(0,maxValue-1);//设定滑动条的范围mThread->startPlay(filePath,width,height);//启动线程显示播放
}
3、启动线程 进行播放
void TransCodeThread::startPlay(QString infile,int width,int height)
{mFilePath = infile;mWidth = width;mHeight = height;start();//启动线程执行run()
}/*在独立线程中对视频进行解码,并通过信号函数sig_GetOneFrame传送每一帧图像*/
void TransCodeThread::run()
{time.start();char filePath[1024]={0};strcpy(filePath,mFilePath.toUtf8().data());FILE *fp_yuv_rgb = fopen(filePath,"rb"); //打开视频文件 int width = mWidth;int height = mHeight;if (fp_yuv_rgb == NULL) return;/**判断文件类型**/QString fileright = mFilePath.right(3);if(fileright =="rgb"){m_filetype=1;}else if(fileright =="yuv"){m_filetype=0;}//获取文件的大小fseek( fp_yuv_rgb,0,SEEK_END ); //把文件指针定位到文件尾 int file_size=ftell( fp_yuv_rgb );//获取文件的大小fseek( fp_yuv_rgb,0,SEEK_SET );//把文件指针指向开头int yuvSize = width * height *3/2 ;BYTE *yuvBuffer = (BYTE *)malloc(yuvSize);int rgbSize = width *height *sizeof(RGB32);//RGB32为一个结构体 32位BYTE *rgbBuffer = (BYTE *)malloc(rgbSize); //调试显示qDebug()<<file_size;qDebug()<<maxValue;int ReadedSize = 0;//已读文件大小初始化for(int i=0;; i++){if (feof(fp_yuv_rgb))//文件读取结束{//qDebug()<<m_i;break;}int readedsize;if(isMoved)//按下滑块,则修改读取指针的位置{//获取文件指针的位置(滑条被分为与帧数同等分)int pointPosition = file_size * (double)SliderPosition/maxValue;fseek( fp_yuv_rgb, pointPosition , SEEK_SET );ReadedSize = pointPosition ;}if(m_filetype==1)//rgb{readedsize= fread(rgbBuffer,1,rgbSize,fp_yuv_rgb);//注释,YUV2RGB// qDebug()<<readedsize;}else//yuv{readedsize= fread(yuvBuffer,1,yuvSize,fp_yuv_rgb);//读取yuv文件Yuv420p2Rgb32(yuvBuffer, rgbBuffer, width, height);//转换}//把这个RGB数据 用QImage加载QImage tmpImg((uchar *)rgbBuffer,width,height,QImage::Format_RGB32);QImage image = tmpImg.copy(); //把图像复制一份 传递给界面显示if(fps == 25){msleep(20);}else if(fps == 30){msleep(10);}emit sig_GetOneFrame(image); //发送信号//更新已读取文件大小,更改滑块位置ReadedSize += readedsize;if(!isMoved)emit moveSlider(((double)ReadedSize/file_size)*maxValue);//发送进度条移动信号 已读的比例int time_Diff = time.elapsed();//消逝的时间float f = time_Diff/1000.0;//秒转换为毫秒float TotalTime = 0 ;TotalTime += f;//播放的总时间QString TT = QString("%1").arg(TotalTime);qDebug() << TT;}//释放内存free(yuvBuffer);free(rgbBuffer);
}
4、格式转换函数
void TransCodeThread::Yuv420p2Rgb32(const BYTE *yuvBuffer_in,const BYTE *rgbBuffer_out,int width,int height)
{BYTE *yuvBuffer = (BYTE *)yuvBuffer_in;RGB32 *rgb32Buffer = (RGB32 *)rgbBuffer_out;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){int index = y * width + x;int indexY = y * width + x;int indexU = width * height + y / 2 * width / 2 + x / 2;int indexV = width * height + width * height / 4 + y / 2 * width / 2 + x / 2;BYTE Y = yuvBuffer[indexY];BYTE U = yuvBuffer[indexU];BYTE V = yuvBuffer[indexV];RGB32 *rgbNode = &rgb32Buffer[index];rgbNode->rgbRed = Y + 1.402 * (V-128);rgbNode->rgbGreen = Y - 0.34413 * (U-128) - 0.71414*(V-128);rgbNode->rgbBlue = Y + 1.772*(U-128);}}
}
5、实现进度条与暂停的各类函数
//获取视频帧数
int MainWindow::filenumber()
{/*提取三个文本框的内容*/QString filePath = ui->lineEdit_filepath->text();int width = ui->lineEdit_2_width->text().toInt();//toInt()表示将类型转化成intint height = ui->lineEdit_height->text().toInt(); char curfilePath[1024]={0};strcpy(curfilePath,filePath.toUtf8().data());FILE *fp_yuv_rgb = fopen(curfilePath,"rb");//文件指针移到文件尾fseek( fp_yuv_rgb,0,SEEK_END );//获取文件的大小int file_size=ftell( fp_yuv_rgb );int yuvSize = width * height * 3/2 ;int rgbSize = width *height *sizeof(RGB32);/**计算帧数 判断文件类型**/QString fileright = filePath.right(3);static int number;if(fileright =="rgb"){number = file_size/rgbSize;}else if(fileright =="yuv"){number = file_size/yuvSize;}return number;
}
//改变滑块位置的槽函数
void MainWindow::ChangeSliderPosition(int position)
{ ui->horizontalSlider->setValue(position);
}//滑块按下槽函数
void MainWindow::on_horizontalSlider_sliderPressed()
{//qDebug()<<"anxia ";mThread->isMoved = true;
}
//滑块移动槽函数 实时获取滑块的位置
void MainWindow::on_horizontalSlider_sliderMoved(int position)
{mThread->SliderPosition = position;
}
// 滑块松开槽函数
void MainWindow::on_horizontalSlider_sliderReleased()
{mThread->isMoved = false;
}
//暂停按钮槽函数
void MainWindow::on_pushButton_pause_clicked()
{mThread->SliderPosition = ui->horizontalSlider->value();mThread->isMoved = !mThread->isMoved;
}
6、各类槽函数的连接
/*构造函数*/
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);//创建ui页面mThread = new TransCodeThread;//创建类对象/*槽与信号链接*/connect(mThread,SIGNAL(sig_GetOneFrame(QImage)),this,SLOT(slotGetOneFrame(QImage)));//进行图像传递和接收connect(mThread,&TransCodeThread::moveSlider, this, &MainWindow::ChangeSliderPosition);
}/*析构函数*/
MainWindow::~MainWindow()
{delete ui;//删除ui界面
}
基于QT播放器的实现(一)Rgb、YUV格式(附带代码)相关推荐
- 单片机及接口课程设计报告-------基于音乐播放器
目录 课设目的.内容....................................................................................... 1. ...
- VLC+Qt播放器对比测试
开发环境:VS2017 + Qt5.12.5 + Vlc3.0 事先说明 为什么做这个东西. 各个播放器都有各自的优缺点.LibVlc太大,启动慢,对于播放一些短小的特效音视频不太好用,而且进度反馈也 ...
- 基于exoplayer播放器的高斯模糊视频滤镜
最近项目需求,视频滤镜要用高斯模糊.奈何网上全是图片高斯模糊,且模糊的强度不够,效果并不是自己需要的. 于是,打算自己写一个. exoPlayer播放器自带滤镜,所以用这个播放器来做. 滤镜的话,用到 ...
- iOS实现基于VLC播放器的封装效果
前言: 在一些特定场景下,我们获取到的音视频,由于格式比较特殊,用avplayer等播放器是无法播放的,此时,我们可以借助强大的VLC播放器来处理. 原理这里不再赘述,下面我们讲一下如何添加VLC播放 ...
- 基于exoplayer播放器的高斯模糊视频滤镜,整合aar文件,给伸手党
接入步骤如下: 接入步骤 1.aar文件拷贝至app下libs文件夹内 2.在app下的build.gradle中添加(最外层) repositories {flatDir {dirs 'libs'} ...
- JQuery播放器代理--IE下支持wma格式
Jplayer代理类 1/**//** 2* 3* Media 代理 4* @param Object p_play:播放器 5*/ 6var media_player_pro ...
- JY播放器【蜻蜓FM电脑端,附带下载功能】
今天给大家带来一款神器----JY播放器.可以不用打开网页就在电脑端听蜻蜓FM的节目,而且可以直接下载,对于我这种强迫症患者来说真的是神器.我是真的不喜欢电脑任务栏上面密密麻麻. 目前已经支持平台(蜻 ...
- JY播放器【喜马拉雅FM电脑端,附带下载功能】
今天给大家带来一款神器----JY播放器.可以不用打开网页就在电脑端听喜马拉雅FM的节目,而且可以直接下载,对于我这种强迫症患者来说真的是神器.我是真的不喜欢电脑任务栏上面密密麻麻的. 目前已经支持平 ...
- 视频与图像RGB/YUV格式详解
计算机彩色显示器显示色彩的原理与彩色电视机一样,都是采用R(Red).G(Green).B(Blue)相加混色的原理:通过发射出三种不同强度的电子束,使屏幕内侧覆盖的红.绿.蓝磷光材料发光而产生色彩. ...
- 基于海思3559 高效率的 0延时 0拷贝 qt播放器方案
海思的有很好的mpp SDK, 播放视频流的,可以快速的从VDEC(解码)到 VO(显示),但是当我们UI需求比较复杂的时候,需要很多操作界面,比如快进,后退,比如调节摄像头位置等等,这些复杂的UI ...
最新文章
- mdkstc系列器件支持包下载_Find X2系列 Android 11 Beta1 测试版发布
- 《去哪网编程题》统计字符
- iOS实现经典登录页面,手机号自动格式化
- vue省市区三级联动mysql,js/json,html/jsp
- python中协程与函数的区别_python 协程与go协程的区别
- 过完年进入BAT 需要做哪些准备
- 今天最好的生日礼物就是重新找到目标
- HDU-2502 月之数 组合数
- c语言 字节 半字 字,PLC的位,半字节,字节,字介绍
- The P4 Language Specification v1.0.2 Parser
- 虚拟机ping不通宿主机,宿主机能ping通虚拟机
- 792. 高精度减法
- 水仙花数c语言程序解析,C语言求水仙花数代码解析
- MyEclipse6.5的反编译插件的安装
- Moodle安装完全手册
- HP M280 鼠标驱动
- C语言的内存问题总结
- 可视化工具 roto 3t
- Unity Loading转场学习笔记
- UE4 C++ 动态读取图片
热门文章
- shl归纳推理测试题库_强生2020秋招笔试面试经验合集
- 论文的重复率修改方法
- 好项目,不私藏!适用于单片机开发的开源轮子
- java删除非空文件夹
- windows下,可替换telnet的工具tcping.exe
- wincc7.5官网下载及安装配置(适配window10超详细教程)
- dnf服务器运行库,游戏运行库|3DM游戏必备运行库合集安装包(史上最全) V3.0
- oracle查询undo表空间使用率,检查Undo表空间使用情况
- 中国电信与阿里巴巴签署全面战略合作协议
- 视频监控存储解决方案——快速、可靠的视频存储