Ver Fonte

~ brought back video support

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
Alexis Maiquez há 5 anos atrás
pai
commit
154fe905bc

+ 9 - 4
main.cpp

@@ -169,11 +169,11 @@ int main (int argc, char* argv[])
     auto project = WallpaperEngine::Core::CProject::fromFile ("project.json", containers);
     WallpaperEngine::Render::CWallpaper* wallpaper;
 
-    auto projection = project->getWallpaper ()->as <WallpaperEngine::Core::CScene> ()->getOrthogonalProjection ();
+    // auto projection = project->getWallpaper ()->as <WallpaperEngine::Core::CScene> ()->getOrthogonalProjection ();
     // create the window!
     // TODO: DO WE NEED TO PASS MONITOR HERE OR ANYTHING?
     // TODO: FIGURE OUT HOW TO PUT THIS WINDOW IN THE BACKGROUND
-    GLFWwindow* window = glfwCreateWindow (projection->getWidth (), projection->getHeight (), "WallpaperEngine", NULL, NULL);
+    GLFWwindow* window = glfwCreateWindow (1920, 1080, "WallpaperEngine", NULL, NULL);
 
     if (window == nullptr)
     {
@@ -184,8 +184,8 @@ int main (int argc, char* argv[])
 
     glfwMakeContextCurrent (window);
 
-    int windowWidth = projection->getWidth ();
-    int windowHeight = projection->getHeight ();
+    int windowWidth = 1920;
+    int windowHeight = 1080;
 
     // get the real framebuffer size
     glfwGetFramebufferSize (window, &windowWidth, &windowHeight);
@@ -205,7 +205,12 @@ int main (int argc, char* argv[])
     }
     else if (project->getType () == "video")
     {
+        // special steps, running a video needs a root directory change
+        chdir (path.c_str ());
+
         // TODO: BUILD THE VIDEO OBJECT
+        WallpaperEngine::Core::CVideo* video = project->getWallpaper ()->as <WallpaperEngine::Core::CVideo> ();
+        wallpaper = new WallpaperEngine::Render::CVideo (video, containers);
     }
     else
     {

+ 199 - 33
src/WallpaperEngine/Render/CVideo.cpp

@@ -1,7 +1,6 @@
 #include "CVideo.h"
 
 using namespace WallpaperEngine;
-
 using namespace WallpaperEngine::Render;
 
 CVideo::CVideo (Core::CVideo* video, CContainer* container) :
@@ -16,7 +15,7 @@ CVideo::CVideo (Core::CVideo* video, CContainer* container) :
     // Find first video stream
     for (int i = 0; i < m_formatCtx->nb_streams; i++)
     {
-        if (m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
+        if (m_formatCtx->streams [i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
         {
             m_videoStream = i;
             break;
@@ -26,7 +25,7 @@ CVideo::CVideo (Core::CVideo* video, CContainer* container) :
     // Find first audio stream
     for (int i = 0; i < m_formatCtx->nb_streams; i++)
     {
-        if (m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
+        if (m_formatCtx->streams [i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
         {
             m_audioStream = i; 
             break;
@@ -37,12 +36,12 @@ CVideo::CVideo (Core::CVideo* video, CContainer* container) :
     if (m_videoStream == -1)
         throw std::runtime_error ("Failed to find video stream");
 
-    AVCodec* codec = avcodec_find_decoder (m_formatCtx->streams[m_videoStream]->codecpar->codec_id);
+    AVCodec* codec = avcodec_find_decoder (m_formatCtx->streams [m_videoStream]->codecpar->codec_id);
     if (codec == nullptr)
         throw std::runtime_error ("Failed to find codec");
 
     m_codecCtx = avcodec_alloc_context3 (codec);
-    if (avcodec_parameters_to_context (m_codecCtx, m_formatCtx->streams[m_videoStream]->codecpar))
+    if (avcodec_parameters_to_context (m_codecCtx, m_formatCtx->streams [m_videoStream]->codecpar))
         throw std::runtime_error ("Failed to copy codec parameters");
 
     if (avcodec_open2 (m_codecCtx, codec, NULL) < 0)
@@ -52,6 +51,47 @@ CVideo::CVideo (Core::CVideo* video, CContainer* container) :
     m_videoFrameRGB = av_frame_alloc ();
     if (m_videoFrameRGB == nullptr)
         throw std::runtime_error ("Failed to allocate video frame");
+
+    GLfloat texCoords [] = {
+        0.0f, 0.0f,
+        1.0f, 0.0f,
+        0.0f, 1.0f,
+        0.0f, 1.0f,
+        1.0f, 0.0f,
+        1.0f, 1.0f
+    };
+
+    // inverted positions so the final texture is rendered properly
+    GLfloat position [] = {
+        -1.0f, 1.0f, 0.0f,
+        1.0, 1.0f, 0.0f,
+        -1.0f, -1.0f, 0.0f,
+        -1.0f, -1.0f, 0.0f,
+        1.0f, 1.0f, 0.0f,
+        1.0f, -1.0f, 0.0f
+    };
+
+    glGenBuffers (1, &this->m_texCoordBuffer);
+    glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
+    glBufferData (GL_ARRAY_BUFFER, sizeof (texCoords), texCoords, GL_STATIC_DRAW);
+
+    glGenBuffers (1, &this->m_positionBuffer);
+    glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
+    glBufferData (GL_ARRAY_BUFFER, sizeof (position), position, GL_STATIC_DRAW);
+
+    // setup gl things to render the background
+    glGenTextures (1, &this->m_texture);
+    // configure the texture
+    glBindTexture (GL_TEXTURE_2D, this->m_texture);
+    // set filtering parameters, otherwise the texture is not rendered
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    // set texture basic data
+    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, m_codecCtx->width, m_codecCtx->height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+
+    this->setupShaders ();
 }
 
 void CVideo::setSize (int width, int height)
@@ -63,7 +103,7 @@ void CVideo::setSize (int width, int height)
         sws_freeContext (m_swsCtx);
 
     int numBytes = av_image_get_buffer_size (AV_PIX_FMT_RGB24, width, height, 1);
-    m_buffer = (uint8_t*)av_malloc (numBytes * sizeof (uint8_t));
+    m_buffer = (uint8_t*) av_malloc (numBytes * sizeof (uint8_t));
 
     av_image_fill_arrays (m_videoFrameRGB->data, m_videoFrameRGB->linesize, m_buffer, AV_PIX_FMT_RGB24, width, height, 1);
 
@@ -76,24 +116,36 @@ void CVideo::setSize (int width, int height)
 
 void CVideo::render ()
 {
-    // TODO: REWRITE
-    /*
-    irr::video::IVideoDriver* driver = m_context->getDevice ()->getVideoDriver ();
-    int width = driver->getScreenSize ().Width;
-    int height = driver->getScreenSize ().Height;
-
-    m_frameImage = m_context->getDevice ()->getVideoDriver ()->createImage (irr::video::ECOLOR_FORMAT::ECF_R8G8B8,
-                irr::core::dimension2du(width, height));
-
-    setSize (width, height);
+    // do not render using the CWallpaper function, just use this one
+    this->setSize (m_codecCtx->width, m_codecCtx->height);
     getNextFrame ();
     writeFrameToImage ();
 
-    driver->removeTexture (m_frameTexture);
-    m_frameTexture = driver->addTexture ("frameTexture", m_frameImage);
-    m_frameImage->drop ();
-
-    driver->draw2DImage (m_frameTexture, irr::core::vector2di(0));*/
+    // do the actual rendering
+    // write to default's framebuffer
+    glBindFramebuffer (GL_FRAMEBUFFER, GL_NONE);
+
+    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glDisable (GL_BLEND);
+    glDisable (GL_DEPTH_TEST);
+    // do not use any shader
+    glUseProgram (this->m_shader);
+    // activate scene texture
+    glActiveTexture (GL_TEXTURE0);
+    glBindTexture (GL_TEXTURE_2D, this->m_texture);
+    // set uniforms and attribs
+    glEnableVertexAttribArray (this->a_TexCoord);
+    glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
+    glVertexAttribPointer (this->a_TexCoord, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+
+    glEnableVertexAttribArray (this->a_Position);
+    glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
+    glVertexAttribPointer (this->a_Position, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+
+    glUniform1i (this->g_Texture0, 0);
+    // write the framebuffer as is to the screen
+    glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
+    glDrawArrays (GL_TRIANGLES, 0, 6);
 }
 
 void CVideo::getNextFrame ()
@@ -130,8 +182,8 @@ void CVideo::getNextFrame ()
     if (avcodec_receive_frame (m_codecCtx, m_videoFrame) < 0)
         return;
 
-    sws_scale (m_swsCtx, (uint8_t const* const*)m_videoFrame->data, m_videoFrame->linesize,
-            0, m_codecCtx->height, m_videoFrameRGB->data, m_videoFrameRGB->linesize);
+    sws_scale (m_swsCtx, (uint8_t const* const*) m_videoFrame->data, m_videoFrame->linesize,
+               0, m_codecCtx->height, m_videoFrameRGB->data, m_videoFrameRGB->linesize);
 
     av_packet_unref (&packet);
 
@@ -141,19 +193,15 @@ void CVideo::getNextFrame ()
 
 void CVideo::writeFrameToImage ()
 {
-    /*
-     * TODO: REWRITE THIS
-    uint8_t* frameData = m_videoFrameRGB->data[0];
+    uint8_t* frameData = m_videoFrameRGB->data [0];
+
     if (frameData == nullptr)
         return;
 
-    uint32_t imgWidth = m_frameImage->getDimension().Width;
-    uint32_t imgHeight = m_frameImage->getDimension().Height;
-    
-    unsigned char* data = (unsigned char*)m_frameImage->lock ();
-    memcpy (data, frameData, imgWidth * imgHeight * 3);
-    m_frameImage->unlock ();
-     */
+    // bind the texture
+    glBindTexture (GL_TEXTURE_2D, this->m_texture);
+    // give openGL the new image's data
+    glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, m_codecCtx->width, m_codecCtx->height, GL_RGB, GL_UNSIGNED_BYTE, frameData);
 }
 
 void CVideo::restartStream ()
@@ -167,4 +215,122 @@ Core::CVideo* CVideo::getVideo ()
     return this->getWallpaperData ()->as<Core::CVideo> ();
 }
 
+
+void CVideo::setupShaders ()
+{
+    // reserve shaders in OpenGL
+    GLuint vertexShaderID = glCreateShader (GL_VERTEX_SHADER);
+
+    // give shader's source code to OpenGL to be compiled
+    const char* sourcePointer = "#version 120\n"
+                                "attribute vec3 a_Position;\n"
+                                "attribute vec2 a_TexCoord;\n"
+                                "varying vec2 v_TexCoord;\n"
+                                "void main () {\n"
+                                "gl_Position = vec4 (a_Position, 1.0);\n"
+                                "v_TexCoord = a_TexCoord;\n"
+                                "}";
+
+    glShaderSource (vertexShaderID, 1, &sourcePointer, nullptr);
+    glCompileShader (vertexShaderID);
+
+    GLint result = GL_FALSE;
+    int infoLogLength = 0;
+
+    // ensure the vertex shader was correctly compiled
+    glGetShaderiv (vertexShaderID, GL_COMPILE_STATUS, &result);
+    glGetShaderiv (vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+    if (infoLogLength > 0)
+    {
+        char* logBuffer = new char [infoLogLength + 1];
+        // ensure logBuffer ends with a \0
+        memset (logBuffer, 0, infoLogLength + 1);
+        // get information about the error
+        glGetShaderInfoLog (vertexShaderID, infoLogLength, nullptr, logBuffer);
+        // throw an exception about the issue
+        std::string message = logBuffer;
+        // free the buffer
+        delete[] logBuffer;
+        // throw an exception
+        throw std::runtime_error (message);
+    }
+
+    // reserve shaders in OpenGL
+    GLuint fragmentShaderID = glCreateShader (GL_FRAGMENT_SHADER);
+
+    // give shader's source code to OpenGL to be compiled
+    sourcePointer = "#version 120\n"
+                    "uniform sampler2D g_Texture0;\n"
+                    "varying vec2 v_TexCoord;\n"
+                    "void main () {\n"
+                    "gl_FragColor = texture2D (g_Texture0, v_TexCoord);\n"
+                    "}";
+
+    glShaderSource (fragmentShaderID, 1, &sourcePointer, nullptr);
+    glCompileShader (fragmentShaderID);
+
+    result = GL_FALSE;
+    infoLogLength = 0;
+
+    // ensure the vertex shader was correctly compiled
+    glGetShaderiv (fragmentShaderID, GL_COMPILE_STATUS, &result);
+    glGetShaderiv (fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+    if (infoLogLength > 0)
+    {
+        char* logBuffer = new char [infoLogLength + 1];
+        // ensure logBuffer ends with a \0
+        memset (logBuffer, 0, infoLogLength + 1);
+        // get information about the error
+        glGetShaderInfoLog (fragmentShaderID, infoLogLength, nullptr, logBuffer);
+        // throw an exception about the issue
+        std::string message = logBuffer;
+        // free the buffer
+        delete[] logBuffer;
+        // throw an exception
+        throw std::runtime_error (message);
+    }
+
+    // create the final program
+    this->m_shader = glCreateProgram ();
+    // link the shaders together
+    glAttachShader (this->m_shader, vertexShaderID);
+    glAttachShader (this->m_shader, fragmentShaderID);
+    glLinkProgram (this->m_shader);
+    // check that the shader was properly linked
+    result = GL_FALSE;
+    infoLogLength = 0;
+
+    glGetProgramiv (this->m_shader, GL_LINK_STATUS, &result);
+    glGetProgramiv (this->m_shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+    if (infoLogLength > 0)
+    {
+        char* logBuffer = new char [infoLogLength + 1];
+        // ensure logBuffer ends with a \0
+        memset (logBuffer, 0, infoLogLength + 1);
+        // get information about the error
+        glGetProgramInfoLog (this->m_shader, infoLogLength, nullptr, logBuffer);
+        // throw an exception about the issue
+        std::string message = logBuffer;
+        // free the buffer
+        delete[] logBuffer;
+        // throw an exception
+        throw std::runtime_error (message);
+    }
+
+    // after being liked shaders can be dettached and deleted
+    glDetachShader (this->m_shader, vertexShaderID);
+    glDetachShader (this->m_shader, fragmentShaderID);
+
+    glDeleteShader (vertexShaderID);
+    glDeleteShader (fragmentShaderID);
+
+    // get textures
+    this->g_Texture0 = glGetUniformLocation (this->m_shader, "g_Texture0");
+    this->a_Position = glGetAttribLocation (this->m_shader, "a_Position");
+    this->a_TexCoord = glGetAttribLocation (this->m_shader, "a_TexCoord");
+}
+
 const std::string CVideo::Type = "video";

+ 14 - 1
src/WallpaperEngine/Render/CVideo.h

@@ -33,13 +33,26 @@ namespace WallpaperEngine::Render
         void restartStream ();
         void getNextFrame ();
         void writeFrameToImage ();
+        void setupShaders ();
 
         AVFormatContext* m_formatCtx = nullptr;
         AVCodecContext* m_codecCtx = nullptr;
-        AVFrame* m_videoFrame = nullptr;
         AVFrame* m_videoFrameRGB = nullptr;
+        AVFrame* m_videoFrame = nullptr;
         SwsContext* m_swsCtx = nullptr;
         uint8_t* m_buffer = nullptr;
         int m_videoStream = -1, m_audioStream = -1;
+
+        /**
+         * The texture used for the video output
+         */
+        GLuint m_texture;
+        GLuint m_texCoordBuffer;
+        GLuint m_positionBuffer;
+        GLuint m_shader;
+        // shader variables
+        GLint g_Texture0;
+        GLint a_Position;
+        GLint a_TexCoord;
     };
 };

+ 2 - 3
src/WallpaperEngine/Render/CWallpaper.h

@@ -99,6 +99,8 @@ namespace WallpaperEngine::Render
          * The depthbuffer used for the scene output
          */
         GLuint m_sceneDepthBuffer;
+
+    private:
         /**
          * The texture used for the scene output
          */
@@ -108,7 +110,6 @@ namespace WallpaperEngine::Render
         GLuint m_shader;
         // shader variables
         GLint g_Texture0;
-        GLint g_ModelViewProjectionMatrix;
         GLint a_Position;
         GLint a_TexCoord;
 
@@ -120,8 +121,6 @@ namespace WallpaperEngine::Render
          * Setups OpenGL's shaders for this wallpaper backbuffer
          */
         void setupShaders ();
-
-    private:
         /**
          * The type of background this wallpaper is (used
          */