|
|
@@ -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";
|