qml使用opengl渲染yuv__opengl

來源:互聯網
上載者:User

前言 使用qml製作播放器兩種架構的比較 前輩們的肩膀 載入Shader語言 Sharder簡要說明 Sharder的載入 qml渲染流程 opengl的渲染 opengl 對yuv資料的要求

前言

使用qml製作視頻播放器。在視訊框架解碼出來後,最後免不了還要交給qml還顯示。 使用qml製作播放器,兩種架構的比較

qml提供圖片傳入介面,解碼完成後,將QImage 交給qml顯示。
這種直接拋棄了。
原因是:
1,圖片傳輸太慢
2,整個動作是交個cpu來執行的,在效能弱的機子上,重新整理圖片很慢
自己實現繼承自QQuickItem的類,資料在Item內部流轉,然後像使用普通qml控制項的方式來調用相應的功能。
這是推薦使用的方式。QtAV就是這麼弄的。但是它封裝的太好了,很多時候,我們可能只需要其中一點點的功能模組,拆解起來很難。因此不得不又造了一遍輪子。 前輩們的肩膀

qt5_qml_Opengl_shader,這篇部落格已經完成的差不多了。但還是寫了一遍,有些細節可能與自己理解的不一樣。有的細節要特別注意處理一下。 載入Shader語言 Sharder簡要說明

Sharder的說明,網上汗牛充棟。
我們用到的功能:簡短點說說就是,告訴opengl你要傳入的三維物體形狀和渲染所需的顏色。 Sharder的載入

我沒有選擇將sharder內容直接包含在代碼中做法,而是單獨放到了一個資源檔中。

沒有選擇將sharder內容直接包含在代碼中做法,而是單獨放到了一個資源檔中。m_program = new QOpenGLShaderProgram();bool ok0 = m_program->addShaderFromSourceFile(QOpenGLShader::Vertex,":/os/openglResource/qmlopenglvideovertexshader.vsh");bool ok1 = false;if(QOpenGLContext::currentContext()->isOpenGLES()){//這裡opengl與opengles載入不同的Shader,不用一樣的是因為,兩者還是有那麼一點點的區別的(關鍵詞precision在opengl中沒有)     ok1 = m_program->addShaderFromSourceFile(QOpenGLShader::Fragment,":/os/openglResource/qmlopenglvideofragmentshader.fsh");}else{     ok1 = m_program->addShaderFromSourceFile(QOpenGLShader::Fragment,":/os/openglResource/qmlopenglvideofragmentshader.frag");}

其中opengl es 載入了不同的fragmentshader,因為opengl和opengl es還是有那麼一點不同的,這個要取決於裝置
主要是這裡的區別:

//這裡的宏判定必須加,不然絕大部分的android tv不會顯示#ifdef GL_FRAGMENT_PRECISION_HIGHprecision highp float;#elseprecision mediump float;#endif
qml渲染流程

opengl作為組件被qml使用,存在著一個誰先渲染的問題。同一地區,後渲染的會覆蓋之前渲染的。

這個渲染的次序決定了層疊的次序

//先渲染qml,再渲染openglconnect(window(), &QQuickWindow::afterRendering, m_renderer, &ALOpenglQmlVideoShowRenderer::paint, Qt::DirectConnection);//先渲染opengl,再渲染qmlconnect(window(), &QQuickWindow::afterRendering, m_renderer, &ALOpenglQmlVideoShowRenderer::paint, Qt::DirectConnection);
opengl的渲染

其實這裡沒有什麼好說的,感覺整個流程是死的,沒有太大的發揮空間。
在整個demo中,我盡量使用Qt的opengl類,實在沒有辦法了才用opengl原生的。
但我總覺得Qt這裡做的不是很好。

m_program->bind();int vertsLocation = m_program->attributeLocation("vertexIn");int textureLocation = m_program->attributeLocation("textureIn");m_program->enableAttributeArray(vertsLocation);m_program->enableAttributeArray(textureLocation);m_program->setAttributeArray(vertsLocation, GL_FLOAT, vertexVertices,2);m_program->setAttributeArray(textureLocation, GL_FLOAT, textureVertices,2);textureUniformY = m_program->uniformLocation("tex_y");textureUniformU = m_program->uniformLocation("tex_u");textureUniformV = m_program->uniformLocation("tex_v");glViewport(m_nX, m_viewportSize.height() - m_nY - m_nHeight , m_nWidth, m_nHeight);QByteArray t_byteArray;//{QMutexLocker locker(&m_imageDataMutex);t_byteArray= m_imageData;}m_pBufYuv420p = (unsigned char*)t_byteArray.data();glActiveTexture(GL_TEXTURE0);//使用來自y資料產生紋理glBindTexture(GL_TEXTURE_2D, id_y);//使用記憶體中m_pBufYuv420p資料建立真正的y資料紋理glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW, m_nVideoH, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pBufYuv420p);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);//載入u資料紋理glActiveTexture(GL_TEXTURE1);//啟用紋理單元GL_TEXTURE1glBindTexture(GL_TEXTURE_2D, id_u);glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p + m_nVideoH*m_nVideoW);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);//載入v資料紋理glActiveTexture(GL_TEXTURE2);//啟用紋理單元GL_TEXTURE2glBindTexture(GL_TEXTURE_2D, id_v);glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,(char*)m_pBufYuv420p + m_nVideoH*m_nVideoW * 5 / 4);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glUniform1i(textureUniformY, 0);//指定u紋理要使用新值glUniform1i(textureUniformU, 1);//指定v紋理要使用新值glUniform1i(textureUniformV, 2);// glClearColor(0.0, 0.5, 0.0, 1.0);// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Draw the triangle !glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // Starting from vertex 0; 3 vertices total -> 1 trianglem_program->disableAttributeArray(textureLocation);m_program->disableAttributeArray(vertsLocation);m_program->release();// Not strictly needed for this example, but generally useful for when// mixing with raw OpenGL.m_window->resetOpenGLState();

其中需要注意的是

// glClearColor(0.0, 0.5, 0.0, 1.0);  // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

作用是清空背景,如果開啟的話。先前繪製的內容都會被清空。 opengl 對yuv資料的要求

除了格式要求,還有就是傳入的資料中沒有沒用的資料。
也就是記憶體對齊為1。

glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,(char*)m_pBufYuv420p + m_nVideoH*m_nVideoW * 5 / 4);

這裡原始碼
learn_openglunderqml_5.zip

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.