diff --git a/AVQt/output/OpenGLRenderer.cpp b/AVQt/output/OpenGLRenderer.cpp
index 045f3a4ad9d10263f03ad18c78f9827b47849bf7..fa2f2ef6e736c5319937f7169696d9a9158d5ce0 100644
--- a/AVQt/output/OpenGLRenderer.cpp
+++ b/AVQt/output/OpenGLRenderer.cpp
@@ -189,26 +189,27 @@ namespace AVQt {
 
         loadResources();
 
-        d->m_program = new QOpenGLShaderProgram();
+        QByteArray shaderVersionString;
 
         if (context()->isOpenGLES()) {
-            if (!d->m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/textureES.vsh")) {
-                qDebug() << "Vertex shader errors:\n" << d->m_program->log();
-            }
-
-            if (!d->m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/textureES.fsh")) {
-                qDebug() << "Fragment shader errors:\n" << d->m_program->log();
-            }
+            shaderVersionString = "#version 300 es\n";
         } else {
-            if (!d->m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/texture.vsh")) {
-                qDebug() << "Vertex shader errors:\n" << d->m_program->log();
-            }
-
-            if (!d->m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/texture.fsh")) {
-                qDebug() << "Fragment shader errors:\n" << d->m_program->log();
-            }
+            shaderVersionString = "#version 330 core\n";
         }
 
+        QFile vsh{":/shaders/texture.vsh"};
+        QFile fsh{":/shaders/texture.fsh"};
+        vsh.open(QIODevice::ReadOnly);
+        fsh.open(QIODevice::ReadOnly);
+        QByteArray vertexShader = vsh.readAll().prepend(shaderVersionString);
+        QByteArray fragmentShader = fsh.readAll().prepend(shaderVersionString);
+        vsh.close();
+        fsh.close();
+
+        d->m_program = new QOpenGLShaderProgram();
+        d->m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader);
+        d->m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader);
+
         d->m_program->bindAttributeLocation("vertex", OpenGLRendererPrivate::PROGRAM_VERTEX_ATTRIBUTE);
         d->m_program->bindAttributeLocation("texCoord", OpenGLRendererPrivate::PROGRAM_TEXCOORD_ATTRIBUTE);
 
@@ -379,34 +380,89 @@ namespace AVQt {
                     }
 
                     if (firstFrame) {
+                        bool VTexActive = false, UTexActive = false;
+                        QSize YSize, USize, VSize;
+                        QOpenGLTexture::TextureFormat textureFormatY, textureFormatU, textureFormatV;
+                        QOpenGLTexture::PixelFormat pixelFormatY, pixelFormatU, pixelFormatV;
+                        QOpenGLTexture::PixelType pixelType;
+                        switch (static_cast<AVPixelFormat>(d->m_currentFrame->format)) {
+                            case AV_PIX_FMT_BGRA:
+                                YSize = QSize(d->m_currentFrame->width, d->m_currentFrame->height);
+                                textureFormatY = QOpenGLTexture::RGBA8_UNorm;
+                                pixelFormatY = QOpenGLTexture::BGRA;
+                                pixelType = QOpenGLTexture::UInt8;
+                                break;
+                            case AV_PIX_FMT_YUV420P:
+                                YSize = QSize(d->m_currentFrame->width, d->m_currentFrame->height);
+                                USize = VSize = QSize(d->m_currentFrame->width / 2, d->m_currentFrame->height / 2);
+                                textureFormatY = textureFormatU = textureFormatV = QOpenGLTexture::R8_UNorm;
+                                pixelFormatY = pixelFormatU = pixelFormatV = QOpenGLTexture::Red;
+                                pixelType = QOpenGLTexture::UInt8;
+                                UTexActive = VTexActive = true;
+                                break;
+                            case AV_PIX_FMT_YUV420P10:
+                                YSize = QSize(d->m_currentFrame->width, d->m_currentFrame->height);
+                                USize = VSize = QSize(d->m_currentFrame->width / 2, d->m_currentFrame->height / 2);
+                                textureFormatY = textureFormatU = textureFormatV = QOpenGLTexture::R16_UNorm;
+                                pixelFormatY = pixelFormatU = pixelFormatV = QOpenGLTexture::Red;
+                                pixelType = QOpenGLTexture::UInt16;
+                                UTexActive = VTexActive = true;
+                                break;
+                            case AV_PIX_FMT_NV12:
+                                YSize = QSize(d->m_currentFrame->width, d->m_currentFrame->height);
+                                USize = QSize(d->m_currentFrame->width / 2, d->m_currentFrame->height / 2);
+                                textureFormatY = QOpenGLTexture::R8_UNorm;
+                                textureFormatU = QOpenGLTexture::RG8_UNorm;
+                                pixelFormatY = QOpenGLTexture::Red;
+                                pixelFormatU = QOpenGLTexture::RG;
+                                pixelType = QOpenGLTexture::UInt8;
+                                UTexActive = true;
+                                break;
+                            case AV_PIX_FMT_P010:
+                                YSize = QSize(d->m_currentFrame->width, d->m_currentFrame->height);
+                                USize = QSize(d->m_currentFrame->width / 2, d->m_currentFrame->height / 2);
+                                textureFormatY = QOpenGLTexture::R16_UNorm;
+                                textureFormatU = QOpenGLTexture::RG16_UNorm;
+                                pixelFormatY = QOpenGLTexture::Red;
+                                pixelFormatU = QOpenGLTexture::RG;
+                                pixelType = QOpenGLTexture::UInt16;
+                                UTexActive = true;
+                                break;
+                            default:
+                                qWarning("[AVQt::OpenGLRenderer] Unsupported pixel format");
+                                break;
+                        }
                         d->m_yTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
-                        d->m_uTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
-                        d->m_vTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
-                        d->m_yTexture->setSize(d->m_currentFrame->width, d->m_currentFrame->height);
-                        d->m_uTexture->setSize(d->m_currentFrame->width / 2, d->m_currentFrame->height / 2);
-                        d->m_vTexture->setSize(d->m_currentFrame->width / 2, d->m_currentFrame->height / 2);
-                        d->m_yTexture->setFormat(QOpenGLTexture::RGBA16_UNorm);
-                        d->m_uTexture->setFormat(QOpenGLTexture::RGBA16_UNorm);
-                        d->m_vTexture->setFormat(QOpenGLTexture::RGBA16_UNorm);
-                        d->m_yTexture->allocateStorage(QOpenGLTexture::Red, QOpenGLTexture::UInt16);
-                        d->m_uTexture->allocateStorage(QOpenGLTexture::RG, QOpenGLTexture::UInt16);
-                        d->m_vTexture->allocateStorage(QOpenGLTexture::Red, QOpenGLTexture::UInt16);
-//                            d->m_uTexture = new QOpenGLTexture(
-//                                    QImage(d->m_currentFrame->width / 2, d->m_currentFrame->height / 2, QImage::Format_RGBX64));
-//                            d->m_vTexture = new QOpenGLTexture(
-//                                    QImage(d->m_currentFrame->width / 2, d->m_currentFrame->height / 2, QImage::Format_RGBX64));
-
+                        d->m_yTexture->setSize(YSize.width(), YSize.height());
+                        d->m_yTexture->setFormat(textureFormatY);
                         d->m_yTexture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
-                        d->m_uTexture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
-                        d->m_vTexture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
+                        d->m_yTexture->allocateStorage(pixelFormatY, pixelType);
+                        if (UTexActive) {
+                            d->m_uTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+                            d->m_uTexture->setSize(USize.width(), USize.height());
+                            d->m_uTexture->setFormat(textureFormatU);
+                            d->m_uTexture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
+                            d->m_uTexture->allocateStorage(pixelFormatU, pixelType);
+                        }
+                        if (VTexActive) {
+                            d->m_vTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+                            d->m_vTexture->setSize(VSize.width(), VSize.height());
+                            d->m_vTexture->setFormat(textureFormatV);
+                            d->m_vTexture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
+                            d->m_vTexture->allocateStorage(pixelFormatV, pixelType);
+                        }
                     }
 //                    qDebug("Frame duration: %ld ms", d->m_currentFrameTimeout);
                     if (differentPixFmt) {
                         d->m_program->bind();
                     }
                     d->m_yTexture->bind(0);
-                    d->m_uTexture->bind(1);
-                    d->m_vTexture->bind(2);
+                    if (d->m_uTexture) {
+                        d->m_uTexture->bind(1);
+                    }
+                    if (d->m_vTexture) {
+                        d->m_vTexture->bind(2);
+                    }
                     switch (d->m_currentFrame->format) {
                         case AV_PIX_FMT_BGRA:
                             d->m_yTexture->setData(QOpenGLTexture::PixelFormat::BGRA, QOpenGLTexture::UInt8,
@@ -473,8 +529,12 @@ namespace AVQt {
             d->m_program->bind();
             if (!d->m_yTexture->isBound(0)) {
                 d->m_yTexture->bind(0);
-                d->m_uTexture->bind(1);
-                d->m_vTexture->bind(2);
+                if (d->m_uTexture) {
+                    d->m_uTexture->bind(1);
+                }
+                if (d->m_vTexture) {
+                    d->m_vTexture->bind(2);
+                }
             }
 
             d->m_vao.bind();
@@ -490,8 +550,12 @@ namespace AVQt {
             d->m_vbo.release();
             d->m_program->release();
             d->m_yTexture->release(0);
-            d->m_uTexture->release(1);
-            d->m_vTexture->release(2);
+            if (d->m_uTexture) {
+                d->m_uTexture->release(1);
+            }
+            if (d->m_vTexture) {
+                d->m_vTexture->release(2);
+            }
         }
 
 //        int height = this->height();
diff --git a/AVQt/output/private/OpenGLRenderer_p.h b/AVQt/output/private/OpenGLRenderer_p.h
index 5092f6e284c40b8a3d33d5d49fef90e9298a8d6a..90a33dbb94c47b4376c6b5261452abcb876190b9 100644
--- a/AVQt/output/private/OpenGLRenderer_p.h
+++ b/AVQt/output/private/OpenGLRenderer_p.h
@@ -23,7 +23,7 @@ namespace AVQt {
      * \private
      * \internal
      */
-    class OpenGLRendererPrivate {
+    class OpenGLRendererPrivate : public QObject {
     public:
         OpenGLRendererPrivate(const OpenGLRendererPrivate &) = delete;
 
diff --git a/AVQt/texture.fsh b/AVQt/texture.fsh
index e79ec55a945551d3cc04ece291cfc78877798b01..e7642a445f567285eec8ce498f5b50eacb339076 100644
--- a/AVQt/texture.fsh
+++ b/AVQt/texture.fsh
@@ -1,5 +1,3 @@
-#version 100
-
 // fragment shader
 
 in vec4 fragColor;// input: interpolated color as rgba-value
@@ -15,37 +13,37 @@ void main() {
     vec2 newTexCoord = vec2(1.0f - texCoord.x, texCoord.y);
 
     if (inputFormat == 0) { // RGB(A)
-        vec3 rgb = texture(textureY, newTexCoord).rgb;
+        vec3 rgb = texture2D(textureY, newTexCoord).rgb;
         finalColor = vec4(rgb, 1.0);
     } else if (inputFormat == 1) { // YUV 4:2:0 with Y plane interleaved UV plane (e.g. NV12 or P010)
         vec3 yuv;
 
         // We had put the Y values of each pixel to the R component by using GL_RED
-        yuv.x = texture(textureY, newTexCoord.st).r - 0.0625;
+        yuv.x = texture2D(textureY, newTexCoord.st).r - 0.0625;
         // We had put the U and V values of each pixel to the R and G components of the
         // texture respectively using GL_RG. Since U, V bytes are interspread
         // in the texture, this is probably the fastest way to use them in the shader
-        yuv.y = texture(textureU, newTexCoord.st).r - 0.5;
-        yuv.z = texture(textureU, newTexCoord.st).g - 0.5;
+        yuv.y = texture2D(textureU, newTexCoord.st).r - 0.5;
+        yuv.z = texture2D(textureU, newTexCoord.st).g - 0.5;
         // The numbers are just YUV to RGB conversion constants
-        vec3 rgb = mat3(1, 1, 1,
-        0, -0.39465, 2.03211,
-        1.13983, -0.58060, 0) * yuv;
+        vec3 rgb = mat3(1.0, 1.0, 1.0,
+        0.0, -0.39465, 2.03211,
+        1.13983, -0.58060, 0.0) * yuv;
         finalColor = vec4(rgb, 1.0f);
     } else if (inputFormat == 2) { // YUV420P
         vec3 yuv;
 
         // We had put the Y values of each pixel to the R component by using GL_RED
-        yuv.x = texture(textureY, newTexCoord.st).r - 0.0625;
+        yuv.x = texture2D(textureY, newTexCoord.st).r - 0.0625;
         // We had put the U and V values of each pixel to the R and G components of the
         // texture respectively using GL_RG. Since U, V bytes are interspread
         // in the texture, this is probably the fastest way to use them in the shader
-        yuv.y = texture(textureU, newTexCoord.st).r - 0.5;
-        yuv.z = texture(textureV, newTexCoord.st).r - 0.5;
+        yuv.y = texture2D(textureU, newTexCoord.st).r - 0.5;
+        yuv.z = texture2D(textureV, newTexCoord.st).r - 0.5;
         // The numbers are just YUV to RGB conversion constants
-        vec3 rgb = mat3(1, 1, 1,
-        0, -0.39465, 2.03211,
-        1.13983, -0.58060, 0) * yuv;
+        vec3 rgb = mat3(1.0, 1.0, 1.0,
+        0.0, -0.39465, 2.03211,
+        1.13983, -0.58060, 0.0) * yuv;
         finalColor = vec4(rgb, 1.0f);
     } else if (inputFormat == 3) { // YUV420P10
         vec3 yuv;
@@ -53,14 +51,14 @@ void main() {
         // Multiply every value with 2^6 = 64, because the values are stored in the lower 10 bits,
         // but have to be in the upper 10 bits for correct calculation
         // We had put the Y values of each pixel to the R component of every texture by using GL_RED
-        yuv.x = texture(textureY, newTexCoord.st).r * 64 - 0.0625;
-        yuv.y = texture(textureU, newTexCoord.st).r * 64 - 0.5;
-        yuv.z = texture(textureV, newTexCoord.st).r * 64 - 0.5;
+        yuv.x = texture2D(textureY, newTexCoord.st).r * 64.0 - 0.0625;
+        yuv.y = texture2D(textureU, newTexCoord.st).r * 64.0 - 0.5;
+        yuv.z = texture2D(textureV, newTexCoord.st).r * 64.0 - 0.5;
         // The numbers are just YUV to RGB conversion constants
-        vec3 rgb = mat3(1, 1, 1,
-        0, -0.39465, 2.03211,
-        1.13983, -0.58060, 0) * yuv;
+        vec3 rgb = mat3(1.0, 1.0, 1.0,
+        0.0, -0.39465, 2.03211,
+        1.13983, -0.58060, 0.0) * yuv;
 
         finalColor = vec4(rgb, 1.0);
     }
-}
+}
\ No newline at end of file
diff --git a/AVQt/texture.vsh b/AVQt/texture.vsh
index 86b42ff7498668ec82e2f2ee40530bbc0b3572ca..1c47710c61b94905f34afeaf2cdd50a5ea3eaf9a 100644
--- a/AVQt/texture.vsh
+++ b/AVQt/texture.vsh
@@ -1,6 +1,3 @@
-#version 100
-
-// GLSL version 3.3
 // vertex shader
 
 layout(location = 0) in vec3 position;   // input:  attribute with index '0' with 3 elements per vertex
@@ -18,4 +15,4 @@ void main() {
   fragColor = vec4(0.5, 1.0, 0.3, 1.0);
   texCoord = texcoords;
 //  texID = texnr;
-}
+}
\ No newline at end of file
diff --git a/Player/main.cpp b/Player/main.cpp
index 2a0341a960361e7a7751094bd9f2f602eada4938..7a4cef9d521e602b0ce52c88599296c90e85133a 100644
--- a/Player/main.cpp
+++ b/Player/main.cpp
@@ -68,7 +68,7 @@ int main(int argc, char *argv[]) {
 
     AVQt::IDecoder *videoDecoder;
 #ifdef Q_OS_LINUX
-    videoDecoder = new AVQt::DecoderMMAL;
+    videoDecoder = new AVQt::DecoderVAAPI;
 #elif defined(Q_OS_WINDOWS)
     videoDecoder = new AVQt::DecoderDXVA2();
 #else
@@ -110,4 +110,4 @@ int main(int argc, char *argv[]) {
     });
 
     return QApplication::exec();
-}
+}
\ No newline at end of file