完整代码链接:y4m解析基于QML渲染.y4m格式2160p文件(yuv420帧数据)-网络游戏文档类资源-CSDN下载
y4m文件格式:YUV4MPEG2 - MultimediaWiki
y4m测试文件下载:Xiph.org :: Derf's Test Media Collection
本例中使用的是:in_to_tree资源
man.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
id: appWin
visible: true
width: Screen.width
height: Screen.height
flags:Qt.FramelessWindowHint //无边框
property var videoW: width
property var videoH: height
property var sysFps: 60
OSDVideoOutput {
id: localv
width: videoW
height: videoH
}
}
OSDVideoOutput.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Material 2.12
import com.novastar.FrameProvider 1.0
import QtMultimedia 5.4
Rectangle {
property var localIndex: 0
property var localIP: ""
property var mdType: ""
property var itemDel: 0
color: Qt.rgba(136/255, 136/255, 136/255, 0.6)
VideoOutput {
id: display
objectName: "display_"+localIP
anchors.fill: parent
fillMode : VideoOutput.Stretch
source: provider
}
FrameProvider {
id: provider
property var sys_fps: appWin.sysFps
objectName: "provider_"+localIP
uiIndex: localIndex
fpWidth: 3840
fpHegit: 2160
modelType: mdType
ip: localIP //最后初始化
onSys_fpsChanged: {
provider.setFps(sysFps)
}
Component.onCompleted: {
provider.init()
}
Component.onDestruction: {
provider.release();
}
Item {
id: fps
width: parent.width
Text {
id: curFps
text: "fps:" + provider.getCurFps()
font.bold: true
color: "red"
font.pixelSize: 18
Timer {
interval: 1000
running: true
repeat: true
onTriggered: {
curFps.text = "fps:" + provider.getCurFps()
}
}
}
}
}
.y4m文件头解析
char bufData[128] = {0};
char ch = { 0 };
int index = 0;
while (indexread(&ch, 1);
if (ch != '\n')
{
bufData[index] = ch;
index++;
}
else
{
break;
}
}
std::string strData(bufData);
qDebug() << bufData;
std::vector vecResult;
splitStringByChar(strData, vecResult, ' ');
std::string strFrameW = vecResult[1].substr(1, std::string::npos);
std::string strFrameH = vecResult[2].substr(1, std::string::npos);
iFrameW = atoi(strFrameW.c_str());
iFrameH = atoi(strFrameH.c_str());
m_iCurFrameSize = iFrameW * iFrameH * 3 / 2;
memset(bufData, 0, sizeof(bufData));
m_fin->read(bufData, sizeof("FRAME"));
.y4m文件帧解析
len = m_fin->read(m_arrFrameData.data(), m_iCurFrameSize).gcount();
if (len==0 ||(len > 0 && len != m_iCurFrameSize))
{
//不够一帧数据,不渲染,从文件头开始重新读取
//获取程序当前运行目录
m_fin->close();
QString fileName = QCoreApplication::applicationDirPath();
fileName += QString("/in_to_tree_2160p50.y4m");
std::string strTestFileName = fileName.toLatin1().data();
m_fin->open(strTestFileName, std::ios::binary | std::ios::in);
if (m_fin->is_open())
{
m_fin->seekg(SEEK_SET); //将指针指向文件起始位置
//解析y4m文件头
char ch = { 0 };
int index = 0;
while (ch != '\n' && index < sizeof(bufData))
{
m_fin->read(&ch, 1);
bufData[index] = ch;
index++;
}
std::string strData(bufData);
qDebug() << bufData;
std::vector vecResult;
splitStringByChar(strData, vecResult, ' ');
std::string strFrameW = vecResult[1].substr(1, std::string::npos);
std::string strFrameH = vecResult[2].substr(1, std::string::npos);
iFrameW = atoi(strFrameW.c_str());
iFrameH = atoi(strFrameH.c_str());
m_iCurFrameSize = iFrameW * iFrameH * 3 / 2;
//去掉每一帧的标记
memset(bufData, 0, sizeof(bufData));
m_fin->read(bufData, sizeof("FRAME"));
}
}
else
{
*pData = new unsigned char[m_iCurFrameSize];
memcpy(*pData, (char*)m_arrFrameData.data(), m_iCurFrameSize);
m_fin->read(bufData, sizeof("FRAME"));
}